# -*- coding: utf-8 -*-

# Copyright 2009 David Lee Miller
#
# This file is part of POSSM (Python Open Source Scanning Microscopy).
#
# POSSM is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# POSSM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License         
# along with POSSM.  If not, see <http://www.gnu.org/licenses/>.
#                                                                           
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

from client import matplotlib,rcParams,cm,Toolbar,FigureCanvasWxAgg,NavigationToolbar2WxAgg
from client import Figure,nx,RectangleSelector,_load_bitmap
from client import copy,deepcopy,wx,time,ws,sv,os
from client import n #the numpy package
from pylabiv import SpecFigure
import sg_filter as sg
from scipy.ndimage.filters import gaussian_filter,uniform_filter,laplace,sobel,rank_filter,gaussian_laplace
from scipy.ndimage.filters import maximum_filter,median_filter,minimum_filter
from shared.createtree import UnitOrganizer
import string,cmaps,wx.grid
TIMER_ID = wx.NewId()

class FakePkg(object):
	'A container to send old data in.'
	TYPE = 'fake'
	DATATYPE = 'None'
	UO = UnitOrganizer()
	def __init__(self,close=False):
		self.TYPE = None
		self.EXTENT = [0,10,0,10]
		self.SHAPE = (100,100)
		self.LINE = None
		self.data = None
		self.close = close
		self.ZSCALE = 1
		self.ZOUT = 1.0
		self.ZHV = 10.0

#class Plot3D(wx.Frame):
	#ASPECT_W = ws.ASPECT_W
	#ASPECT_H = ws.ASPECT_H
	#ASPECT_SIZE = ws.ASPECT_SIZE
	#TITLE_SIZE = ws.TITLE_SIZE
	#AXES_SIZE = ws.AXES_SIZE
	#DEFAULT_COLOR = ws.DEFAULT_COLOR
	#POINT_TYPE = ws.POINT_TYPE
	#LINE_WEIGHT = ws.LINE_WEIGHT
	#def __init__(self,parent,data):
		#name = 'N/A'
		#wx.Frame.__init__(self, parent, -1, name, style=wx.DEFAULT_FRAME_STYLE)
		#self.fig = Figure((self.ASPECT_W,self.ASPECT_H), self.ASPECT_SIZE)
		#self.canvas = FigureCanvasWxAgg(self, -1, self.fig)
		#self.t = wx.Timer(self, TIMER_ID)
		#self.t.Start(10000)
		#self.txt = None
		#self.parent = parent
		#self.external = False
		#self.x = None
		#self.y = None
		#self.active = True
		#sizer = wx.FlexGridSizer(1,2,0,0)
		#panel_c = wx.Panel(self, -1)
		#sizer2 = wx.FlexGridSizer(2,1,0,0)

		#sizer2.Add(panel_c, 1, wx.EXPAND)
		#sizer.AddGrowableRow(0,1)
		#sizer.AddGrowableCol(0,1)
		#sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
		#sizer.Add(sizer2, 1, wx.LEFT|wx.TOP|wx.GROW)
		#self.SetSizer(sizer)
		#if not hasattr(self, 'subplot'):
                	#self.subplot = self.fig.add_subplot(111)
		#ax = p3.Axes3D(self.subplot)
		#self.statusBar = wx.StatusBar(self, -1)
		#self.statusBar.SetFieldsCount(1)
		#self.SetStatusBar(self.statusBar)
		
		#self.Fit()
		#self.Bind(wx.EVT_TIMER, self.onTimer, id=TIMER_ID)
		#self.Bind(wx.EVT_CLOSE, self.onClose)

		#self.canvas.mpl_connect('motion_notify_event', self.UpdateStatusBar)
		#self.fig.clear()

		#self.Show()


class ScanProperties(wx.Frame):
	'''
	A flexible wx grid panel used to display an arbitrary number of scan attributes.
	'''
	def __init__(self,parent,package,name):
		self.package=package
		pkgdisplay={}
		for i in package.__dict__.keys():
			if type(package.__dict__[i])==tuple or type(package.__dict__[i])==list: pkgdisplay[i] = package.__dict__[i]
		namestr='Scan Properties '+name
		wx.Frame.__init__(self, parent, -1, namestr, style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER|wx.RESIZE_BOX|wx.MAXIMIZE_BOX))
		sizer = wx.FlexGridSizer(1,2,0,0)
		self.param_grid = wx.grid.Grid(self, -1, size=(1, 1))
		self.param_grid.CreateGrid(len(pkgdisplay.keys()), 3)
		self.param_grid.SetRowLabelSize(40)
		self.param_grid.SetColSize(0,100)
		self.param_grid.SetColSize(1,80)
		self.param_grid.SetColSize(2,80)
		self.param_grid.SetColLabelSize(30)
		self.param_grid.EnableDragColSize(1)
		self.param_grid.EnableDragRowSize(0)
		self.param_grid.EnableDragGridSize(0)
		self.param_grid.SetGridLineColour(wx.Colour(0, 0, 0))
		self.param_grid.SetLabelBackgroundColour(wx.Colour(238, 238, 238))
		self.param_grid.SetColLabelValue(0, "Name")
		self.param_grid.SetColLabelValue(1, "Value")
		self.param_grid.SetColLabelValue(2, "Unit")
		self.param_grid.SetMinSize((320, 300))
		attr = wx.grid.GridCellAttr()
		attr.SetReadOnly(True)
		self.param_grid.SetColAttr(0, attr)
		self.param_grid.SetColAttr(2, attr)
		self.param_grid.SetColAttr(1, attr)
		for i,j in enumerate(pkgdisplay.keys()):
			self.param_grid.SetCellValue(i,0,str(j))
			if len(pkgdisplay[j])==2:
				for k in range(1,3): self.param_grid.SetCellValue(i,k,str(pkgdisplay[j][k-1]))
			elif len(pkgdisplay[j])==1: self.param_grid.SetCellValue(i,0,str(pkgdisplay[j][0]))
		sizer.Add(self.param_grid)
		self.SetSizer(sizer)
		self.Fit()
		self.Show()

class LineProfile(wx.Frame):
	'''
	Creates a new window to display line-profile data from the notebook page.
	'''
	ASPECT_W = ws.ASPECT_W
	ASPECT_H = ws.ASPECT_H
	ASPECT_SIZE = ws.ASPECT_SIZE
	TITLE_SIZE = ws.TITLE_SIZE
	AXES_SIZE = ws.AXES_SIZE
	DEFAULT_COLOR = ws.DEFAULT_COLOR
	POINT_TYPE = ws.POINT_TYPE
	LINE_WEIGHT = ws.LINE_WEIGHT
	def __init__(self,parent,name,data,zunit,xscale,xunit,xory='X'):
		wx.Frame.__init__(self, parent, -1, name, style=wx.DEFAULT_FRAME_STYLE)
		self.fig = Figure((self.ASPECT_W,self.ASPECT_H), self.ASPECT_SIZE)
		self.canvas = FigureCanvasWxAgg(self, -1, self.fig)
		self.t = wx.Timer(self, TIMER_ID)
		self.t.Start(10000)
		self.txt = None
		self.parent = parent
		if hasattr(parent,'selprof'): parent.selprof.Disable()
		self.external = False
		self.x = None
		self.y = None
		self.active = True
		self.zunit = zunit
		sizer = wx.FlexGridSizer(1,2,0,0)
		panel_c = wx.Panel(self, -1)
		sizer2 = wx.FlexGridSizer(2,1,0,0)
		
		self.xory=xory
		pro = wx.StaticBox(self, -1, 'Add Profile')
		setpro_label = wx.StaticText(self, -1, 'Set %s Location'%xory)
		if xory == 'X':
			self.setpro = wx.SpinCtrl(self, -1, '0', min=0, max=len(self.parent.display[:,0])-1)
		elif xory == 'Y':
			self.setpro = wx.SpinCtrl(self, -1, '0', min=0, max=len(self.parent.display[0,:])-1)
		else: pass
			
		sizer2a = wx.StaticBoxSizer(pro,wx.VERTICAL)
		if not xory == 'A':
			addpro = wx.Button(self, -1, 'Add to Plot')
			clearpro = wx.Button(self, -1, 'Clear All Profiles')
			setpro_label.SetMinSize((63,37))
			self.setpro.SetMinSize((63,27))
			addpro.SetMinSize((127,27))
			clearpro.SetMinSize((127,27))
			setpro_sizer = wx.BoxSizer(wx.HORIZONTAL)
			setpro_sizer.Add(setpro_label, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
			setpro_sizer.Add(self.setpro, 0, wx.ADJUST_MINSIZE|wx.ALL, 8)
		
			sizer2a.Add(setpro_sizer, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
			sizer2a.Add(addpro, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
			sizer2a.Add(clearpro, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
			sizer2.Add(sizer2a, 1, wx.ADJUST_MINSIZE|wx.ALL, 5)
			addpro.Bind(wx.EVT_BUTTON, self.AddProfile)
			clearpro.Bind(wx.EVT_BUTTON, self.ClearAll)
		
		savgol = wx.StaticBox(self, -1, 'Savitzky-Golay')
		savsizer = wx.BoxSizer(wx.HORIZONTAL)
		sgptssizer = wx.BoxSizer(wx.HORIZONTAL)
		sgpts_label = wx.StaticText(self,-1,'# Points:')
		self.sgpts = wx.SpinCtrl(self, -1, str(5), min=1, max=30)
		sgpts_label.SetMinSize((63,27))
		self.sgpts.SetMinSize((63,27))
		sgptssizer.Add(sgpts_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		sgptssizer.Add(self.sgpts, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		pordersizer = wx.BoxSizer(wx.HORIZONTAL)
		porder_label = wx.StaticText(self,-1,'PolyOrder:')
		self.porder = wx.SpinCtrl(self, -1, str(1), min=1, max=5)
		porder_label.SetMinSize((63,27))
		self.porder.SetMinSize((63,27))
		pordersizer.Add(porder_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		pordersizer.Add(self.porder, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		dordersizer = wx.BoxSizer(wx.HORIZONTAL)
		dorder_label = wx.StaticText(self,-1,'DerivOrder:')
		self.dorder = wx.SpinCtrl(self, -1, str(1), min=0, max=5)
		dorder_label.SetMinSize((63,27))
		self.dorder.SetMinSize((63,27))
		dordersizer.Add(dorder_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		dordersizer.Add(self.dorder, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		self.sgupdate = wx.Button(self, -1, 'Apply')
		self.sgupdate.SetMinSize((127,27))
		sizer2f = wx.StaticBoxSizer(savgol,wx.VERTICAL)
		sizer2f.Add(sgptssizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(pordersizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(dordersizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(self.sgupdate, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		
		sizer2.Add(sizer2f, 1, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(panel_c, 1, wx.EXPAND)
		sizer.AddGrowableRow(0,1)
		sizer.AddGrowableCol(0,1)
		sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
		sizer.Add(sizer2, 1, wx.LEFT|wx.TOP|wx.GROW)
		self.SetSizer(sizer)
		self.data = data
		self.sgupdate.Bind(wx.EVT_BUTTON, self.OnSG)
		
		self.statusBar = wx.StatusBar(self, -1)
		self.statusBar.SetFieldsCount(1)
		self.SetStatusBar(self.statusBar)
		
		self.Fit()
		self.Bind(wx.EVT_TIMER, self.onTimer, id=TIMER_ID)
		self.Bind(wx.EVT_CLOSE, self.onClose)

		self.canvas.mpl_connect('motion_notify_event', self.UpdateStatusBar)
		self.fig.clear()
		if not hasattr(self, 'subplot'):
                	self.subplot = self.fig.add_subplot(111)
		self.fig.subplots_adjust(left=0.15, bottom=0.2)
		xdata=n.array(range(len(data)))*xscale
		self.asdf = self.subplot.plot(xdata,data,lw=self.LINE_WEIGHT)
		self.subplot.set_ylabel("Z Value ("+self.zunit+")", fontsize = self.AXES_SIZE)
		if xory == 'X': xory_r = 'Y'
		else: xory_r = 'X'
		self.subplot.set_xlabel(xory_r+" Distance (%s)"%xunit, fontsize = self.AXES_SIZE)
		
		self.Show()
	
	def OnSG(self,event):
		gradpts = int(self.sgpts.GetValue())
		polyorder = int(self.porder.GetValue())
		sgderiv = int(self.dorder.GetValue())
		if sgderiv > polyorder:
			self.porder.SetValue(int(sgderiv))
			polyorder = sgderiv
		self.display = deepcopy(self.data)
		coeff = sg.calc_coeff(gradpts, polyorder, sgderiv)
		dx = 1
		corr = (1./dx)**sgderiv
		#if sgderiv != 0: corr *= -1
		#else: corr *= 1
		self.display = sg.savitzky_golay(self.display,kernel=2*gradpts+1,order=polyorder,deriv=sgderiv)
		self.subplot.clear()
		self.subplot.set_ylabel("Z Value ("+self.zunit+")", fontsize = self.AXES_SIZE)
		self.subplot.plot(self.display,lw=self.LINE_WEIGHT)
		self.canvas.draw()
	
	def onTimer(self, evt):
		self.canvas.draw()
	
	def onClose(self, evt):
		self.active = False
		self.t.Stop()
		if hasattr(self.parent,'selprof'): self.parent.selprof.Enable()
		if hasattr(self.parent,'proline') and self.xory=='A':
			self.parent.proline.remove()
			self.parent.canvas.draw()
		evt.Skip()
	
	def AddProfile(self, event):
		loc = int(self.setpro.GetValue())
		if self.xory == 'Y':
			self.subplot.plot(self.parent.display[loc,:],lw=self.LINE_WEIGHT)
		elif self.xory == 'X':
			self.subplot.plot(self.parent.display[:,loc],lw=self.LINE_WEIGHT)
		self.canvas.draw()
	
	def ClearAll(self, event):
		self.subplot.clear()
		self.canvas.draw()
	
	def UpdateStatusBar(self, event):
		if event.inaxes:
			self.x, self.y = event.xdata, event.ydata
			self.statusBar.SetStatusText(( "x= " + str(self.x)[:5] +
							"  y=" +str(self.y)[:5] ),0)

class MakeHist(wx.Frame):
	'''
	Creates a histogram for adjusting the z-limits of the image. Takes mouse input and
	uses the selected values to change the image contrast.
	'''
	ASPECT_W = ws.ASPECT_W
	ASPECT_H = ws.ASPECT_H
	ASPECT_SIZE = ws.ASPECT_SIZE
	TITLE_SIZE = ws.TITLE_SIZE
	AXES_SIZE = ws.AXES_SIZE
	DEFAULT_COLOR = ws.DEFAULT_COLOR
	POINT_TYPE = ws.POINT_TYPE
	left = None
	right = None
	def __init__(self,parent,name,data2):
		wx.Frame.__init__(self, parent, -1, name, style=wx.DEFAULT_FRAME_STYLE)
		self.fig = Figure((self.ASPECT_W,self.ASPECT_H), self.ASPECT_SIZE)
		self.canvas = FigureCanvasWxAgg(self, -1, self.fig)
		self.t = wx.Timer(self, TIMER_ID)
		self.t.Start(10000)
		self.txt = None
		self.parent = parent
		self.external = False
		self.x = None
		self.y = None
		self.active = True

		data=n.array([])
		for i in range(data2.shape[0]):
			if n.ptp(data2[i]) > 0: data=n.append(data,data2[i])
		sizer = wx.FlexGridSizer(1,2,0,0)
		panel_c = wx.Panel(self, -1)
		sizer2 = wx.FlexGridSizer(2,1,0,0)
		
		hist = wx.StaticBox(self, -1, 'Level Adjustments')
		setlevels = wx.Button(self, -1, 'Set Custom Levels')
		setauto = wx.Button(self, -1, 'Set Auto Levels')
		setlevels.SetMinSize((127,27))
		setauto.SetMinSize((127,27))
		sizer2a = wx.StaticBoxSizer(hist,wx.VERTICAL)
		sizer2a.Add(setlevels, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2a.Add(setauto, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		area = wx.StaticBox(self, -1, 'Plot Area')
		exleft = wx.Button(self, -1, '<-- L')
		conleft = wx.Button(self, -1, '--> L')
		conright = wx.Button(self, -1, '<-- R')
		exright = wx.Button(self, -1, '--> R')
		exleft.SetMinSize((63,27))
		conleft.SetMinSize((63,27))
		exright.SetMinSize((63,27))
		conright.SetMinSize((63,27))
		sizerl = wx.BoxSizer(wx.HORIZONTAL)
		sizerr = wx.BoxSizer(wx.HORIZONTAL)
		sizer2b = wx.StaticBoxSizer(area,wx.VERTICAL)
		sizerl.Add(exleft, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizerl.Add(conleft, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizerr.Add(conright, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizerr.Add(exright, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2b.Add(sizerl)
		sizer2b.Add(sizerr)
		
		self.histadj = wx.CheckBox(self, -1, label='Expand Y')
		self.histadj.SetMinSize((127,27))
		uphist = wx.StaticBox(self, -1, 'Update Histogram')
		update = wx.Button(self, -1, 'Update')
		update.SetMinSize((127,27))
		sizer2c = wx.StaticBoxSizer(uphist,wx.VERTICAL)
		sizer2c.Add(self.histadj, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2c.Add(update, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		sizer2.Add(sizer2a, 1, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2b, 1, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2c, 1, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(panel_c, 1, wx.EXPAND)
		
		sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
		sizer.Add(sizer2, 1, wx.LEFT|wx.TOP|wx.GROW)
		self.SetSizer(sizer)


		self.statusBar = wx.StatusBar(self, -1)
		self.statusBar.SetFieldsCount(1)
		self.SetStatusBar(self.statusBar)
		
		self.Fit()
		self.Bind(wx.EVT_TIMER, self.onTimer, id=TIMER_ID)
		self.Bind(wx.EVT_CLOSE, self.onClose)
		setlevels.Bind(wx.EVT_BUTTON, self.SetLevels)
		setauto.Bind(wx.EVT_BUTTON, self.SetAuto)
		exright.Bind(wx.EVT_BUTTON, self.ExRight)
		conright.Bind(wx.EVT_BUTTON, self.ConRight)
		exleft.Bind(wx.EVT_BUTTON, self.ExLeft)
		conleft.Bind(wx.EVT_BUTTON, self.ConLeft)
		update.Bind(wx.EVT_BUTTON, self.OnUp)
		self.histadj.Bind(wx.EVT_CHECKBOX, self.OnScale)
		self.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnAdjustL)
		self.canvas.Bind(wx.EVT_RIGHT_DOWN, self.OnAdjustR)
		self.canvas.Bind(wx.EVT_MOUSEWHEEL, self.OnMWheel)
		self.canvas.mpl_connect('motion_notify_event', self.UpdateStatusBar)
		self.fig.clear()
		if not hasattr(self, 'subplot'):
                	self.subplot = self.fig.add_subplot(111)
		self.fig.subplots_adjust(left=0.15, bottom=0.2)
		self.asdf = self.subplot.hist(data.flatten(), 75, normed=1, facecolor='green', alpha=0.75)
		self.subplot.set_xlabel("Z Value", fontsize = self.AXES_SIZE)
		
		self.leftval,self.rightval = self.parent.im.get_clim()
		self.right = self.subplot.axvline(x=self.rightval, color='r', alpha=0.9)
		self.left = self.subplot.axvline(x=self.leftval, color='g', alpha=0.9)
		self.zmax = n.max(data)
		self.zmin = n.min(data)
		self.zwidth = self.zmax-self.zmin
		self.rmult = 0
		self.lmult = 0
		self.Show()
	
	def OnScale(self, event):
		if self.histadj.GetValue():
			ymax = n.mean(self.asdf[0])+n.std(self.asdf[0])
			self.subplot.set_ylim((0,ymax))
		else:
			self.subplot.set_ylim((0,n.array(self.asdf[0]).max()))
		self.canvas.draw()
	
	def OnAdjustL(self, event, draw=True):
		#if self.left: self.left.remove()
		self.leftval = copy(self.x)
		if self.leftval > self.rightval: self.leftval = copy(self.rightval)
		self.left.set_xdata(self.leftval)
		self.subplot.draw_artist(self.left)
		#self.left = self.subplot.axvline(x=self.leftval, color='g', alpha=0.9) #draws the vertical line
		if draw: self.canvas.draw()
	
	def OnMWheel(self, event):
		wheel = event.GetWheelRotation()
		if wheel > 0:
			self.x = self.leftval + self.zwidth/200.
			self.OnAdjustL(None, draw=False)
			self.x = self.rightval + self.zwidth/200.
			self.OnAdjustR(None)
		elif wheel < 0:
			self.x = self.leftval - self.zwidth/200.
			self.OnAdjustL(None, draw=False)
			self.x = self.rightval - self.zwidth/200.
			self.OnAdjustR(None)
	
	def OnAdjustR(self, event, draw=True):
		#if self.right: self.right.remove()
		self.rightval = copy(self.x)
		if self.rightval < self.leftval: self.rightval = copy(self.leftval)
		self.right.set_xdata(self.rightval)
		self.subplot.draw_artist(self.right)
		#self.right = self.subplot.axvline(x=self.rightval, color='r', alpha=0.9) #draws the vertical line
		if draw: self.canvas.draw()
	
	def onClose(self, evt):
		self.active = False
		self.t.Stop()
		evt.Skip()
		
	def onTimer(self, evt):
		self.canvas.draw()
		
	def UpdateStatusBar(self, event):
		if event.inaxes:
			self.x, self.y = event.xdata, event.ydata
			self.statusBar.SetStatusText(( "x= " + str(self.x)[:5] +
							"  y=" +str(self.y)[:5] ),
							0)
	
	def SetLevels(self, event):
		self.parent.SetLim(zmin=self.leftval,zmax=self.rightval)
	
	def SetAuto(self, event):
		zmax = n.mean(self.parent.display)+2*n.std(self.parent.display)
		zmin = n.mean(self.parent.display)-2*n.std(self.parent.display)
		self.parent.SetLim(zmin=zmin,zmax=zmax)
		self.leftval,self.rightval = self.parent.im.get_clim()
		self.x = copy(self.leftval)
		self.OnAdjustL(None)
		self.x = copy(self.rightval)
		self.OnAdjustR(None)
		self.rmult = 0
		self.lmult = 0
		self.canvas.draw()
	
	def OnUp(self, event):
		self.subplot.clear()
		self.asdf = self.subplot.hist(self.parent.display.flatten(), 75, normed=1, facecolor='green', alpha=0.75)
		self.subplot.set_xlabel("Z Value", fontsize = self.AXES_SIZE)
		self.leftval,self.rightval = self.parent.im.get_clim()
		self.right = self.subplot.axvline(x=self.rightval, color='r', alpha=0.9)
		self.left = self.subplot.axvline(x=self.leftval, color='g', alpha=0.9)
		self.OnScale(event)
	
	def ExRight(self, event):
		self.rmult += 1
		zmin = n.min(self.parent.display)
		zmax = n.max(self.parent.display)
		width = (zmax-zmin)
		adj = 0.05*width
		self.x = zmax + self.rmult*adj
		self.OnAdjustR(None)
		
	def ConRight(self, event):
		self.rmult -= 1
		zmin = n.min(self.parent.display)
		zmax = n.max(self.parent.display)
		width = (zmax-zmin)
		adj = 0.05*width
		self.x = zmax + self.rmult*adj
		self.OnAdjustR(None)
		
	def ExLeft(self, event):
		self.lmult -= 1
		zmin = n.min(self.parent.display)
		zmax = n.max(self.parent.display)
		width = (zmax-zmin)
		adj = 0.05*width
		self.x = zmin + self.lmult*adj
		self.OnAdjustL(None)
		
	def ConLeft(self, event):
		self.lmult += 1
		zmin = n.min(self.parent.display)
		zmax = n.max(self.parent.display)
		width = (zmax-zmin)
		adj = 0.05*width
		self.x = zmin + self.lmult*adj
		self.OnAdjustL(None)


class MyNavigationToolbar(NavigationToolbar2WxAgg):
	"""
	Extend the default wx toolbar with your own event handlers
	"""
	ON_IV = wx.NewId()
	ON_GRAY = wx.NewId()
	ON_SPEC = wx.NewId()
	ON_MASK = wx.NewId()
	ON_SPECDISP = wx.NewId()
	def __init__(self, parent, canvas, cankill, specselect=False):
		NavigationToolbar2WxAgg.__init__(self, canvas)
		self.a = None
		self.fig = None
		self.transiv = None
		self.ivsw = 0
		self.graysw = 0
		self.setcolor = cm.jet
		self.parent = parent
		# for simplicity I'm going to reuse a bitmap from wx, you'll
		# probably want to add your own.
		#if specselect:
			#self.AddSimpleTool(self.ON_SPEC, _load_bitmap('stock_close.xpm'),
						#'Select Spectroscopy Points', 'Toggle Spectroscopy Selector')
			#wx.EVT_TOOL(self, self.ON_SPEC, self.parent.toggle_selector)
	
	def _addMaskToggle(self):
		self.AddSimpleTool(self.ON_MASK, _load_bitmap('stock_close.xpm'),
					'Toggle Spectroscopy Mask', 'Toggle Spectroscopy Mask')
		wx.EVT_TOOL(self, self.ON_MASK, self.parent.toggle_mask)
	
	def _addSpecToggle(self):
		self.AddSimpleTool(self.ON_SPECDISP, _load_bitmap('stock_close.xpm'),
					'Open Spectroscopy Viewer', 'Open Spectroscopy Viewer')
		wx.EVT_TOOL(self, self.ON_SPECDISP, self.parent.toggle_spec)

class NotebookPage(wx.Panel):
	NB_TYPE = 'image'
	im = None
	transspec = None
	mask=None
	imagepath=ws.IMAGEPATH
	#cmap = {'gray':cm.gray,'pink':cm.pink,'hot':cm.hot,'jet':cm.jet,'summer':cm.summer,'spring':cm.spring,\
	#'winter':cm.winter,'autumn':cm.autumn,'flag':cm.flag,'hsv':cm.hsv,'prism':cm.prism,\
	#'stern':cm.gist_stern,'rainbow':cm.gist_rainbow,'earth':cm.gist_earth,'ncar':cm.gist_ncar,'cool':cm.cool,\
	#'copper':cm.copper,'bone':cm.bone}
	#cmap_r = {'gray':cm.gray_r,'pink':cm.pink_r,'hot':cm.hot_r,'jet':cm.jet_r,'summer':cm.summer_r,'spring':cm.spring_r,\
	#'winter':cm.winter_r,'autumn':cm.autumn_r,'flag':cm.flag_r,'hsv':cm.hsv_r,'prism':cm.prism_r,\
	#'stern':cm.gist_stern_r,'rainbow':cm.gist_rainbow_r,'earth':cm.gist_earth_r,'ncar':cm.gist_ncar_r,'cool':cm.cool_r,\
	#'copper':cm.copper_r,'bone':cm.bone_r}
	cmap = cmaps.cmap
	cmap_r = cmaps.cmap_r
	interps = ['--Interp--','bilinear','bicubic','nearest','spline16','spline36',\
	'hanning','hamming','hermite','kaiser','quadric','catrom','gaussian','bessel','mitchell',\
	'sinc','lanczos','blackman']
	currcmap = cmap[ws.DEFAULT_CMAP]
	currinterp = ws.DEFAULT_INTERP
	currfrad = 1
	bkim = None
	curralpha = 1.0
	lineN=0
	ax = 0
	ay = 0
	pave = 0
	coeff = []
	gradpts = 3
	polyorder = 1
	sgderiv = 1
	direc = 0
	mblayer = 0
	dist_unit = ['Volts','Angstroms','Nanometers','Microns']
	current_unit = ['Volts','NanoAmps','PicoAmps']
	xyunit = dist_unit[1]
	zunit = dist_unit[1]
	iunit = current_unit[0]
	scalebar=[None,None]
	fps = ws.MAX_FPS
	def __init__(self,frame,parent,pagenum,editor=None):
		wx.Panel.__init__(self,parent)
		self.parent = parent
		self.frame = frame
		self.pagenum = pagenum
		self.editor=editor
	
	def addPlot(self,figure,datapkg,addlabels=None,smiley=False,fake=False):
		self.figure = figure
		if smiley:
			self.data = datapkg.data
			self.display = datapkg.data
		else:
			if datapkg.SHAPE[0] == datapkg.SHAPE[1]:
				if hasattr(datapkg,'IMAGEDATA'):
					self.data = n.array(datapkg.IMAGEDATA[0][0])
					self.display = n.array(deepcopy(datapkg.IMAGEDATA[0][0]))
				elif fake:
					self.data = n.eye(datapkg.SHAPE[0])
					self.display = n.eye(datapkg.SHAPE[0])
					for i in range(len(self.display[:])):
						for j in range(len(self.display[0,:])):
							#self.data[i,j] = 2*n.sin(i/4.)+2*n.sin(j/4.)
							#self.display[i,j] = 2*n.sin(i/4.)+2*n.sin(j/4.)
							self.data[i,j] = 2*n.cos(0.125*(4*n.pi/2.46)*(1/n.sqrt(3.))*j)+2*n.cos(0.125*(2*n.pi/2.46)*((1/n.sqrt(3.))*j+i))+2*n.cos(0.125*(2*n.pi/2.46)*((-1/n.sqrt(3.))*j+i))
							self.display[i,j] = 2*n.cos(0.125*(4*n.pi/2.46)*(1/n.sqrt(3.))*j)+2*n.cos(0.125*(2*n.pi/2.46)*((1/n.sqrt(3.))*j+i))+2*n.cos(0.125*(2*n.pi/2.46)*((-1/n.sqrt(3.))*j+i))
				else:
					self.data = n.zeros(datapkg.SHAPE)
					self.display = n.zeros(datapkg.SHAPE)
			else:
				self.data = n.zeros(datapkg.SHAPE)
				self.display = n.zeros(datapkg.SHAPE)
				self.display[0,1] = 1
		if datapkg.TYPE in self.frame.imagespec:
			specselect=True
			self.extent = None
			self.spec_mask=datapkg.SPEC_MASK
			self.GRIDX = datapkg.GRIDX
			self.GRIDY = datapkg.GRIDY
			self.checker = datapkg.CHECKER
		else:
			specselect=False
			self.extent = datapkg.EXTENT
		if hasattr(datapkg,'ZSCALE'): self.ZSCALE = datapkg.ZSCALE
		else: self.ZSCALE = 1
		if hasattr(datapkg, 'ZOUT'): self.ZOUT = datapkg.ZOUT
		else: self.ZOUT = 1.0
		if hasattr(datapkg, 'ZHV'): self.ZHV = datapkg.ZHV
		else: self.ZHV = 10.0
		self.UO = datapkg.UO
		self.shape = datapkg.SHAPE
		self.canvas = FigureCanvasWxAgg(self, -1, figure)
		self.toolbar = MyNavigationToolbar(self,self.canvas, True, specselect=specselect)
		self.toolbar.Realize()
		self._set_layout(addlabels=addlabels)
		self.subplot = figure.add_subplot(111)
		self.scalebar=[None,None]
		if self.extent:
			self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			interpolation=self.currinterp)
			self.subplot.set_xlabel('X (Pixels)')
			self.subplot.set_ylabel('Y (Pixels)')
			#levels = n.arange(self.display.min(), self.display.max(), self.display.std())
			#CS = self.subplot.contour(self.display, levels,origin='lower',linewidths=2)
			#self.subplot.clabel(CS,inline=1,fmt='%1.1f',fontsize=12)
		else:
			self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			interpolation=self.currinterp)
			self.subplot.set_xlabel('X (Pixels)')
			self.subplot.set_ylabel('Y (Pixels)')
		#if specselect:
			#self.span = RectangleSelector(self.im.axes, self.onselect,drawtype='box',useblit=True,\
			#minspanx=0,minspany=0)
		self.colorbar = self.figure.colorbar(self.im,shrink=0.8)
		self.colorbar.draw_all()
		self.subplot.set_title('Scan No. '+self.SCAN)
		#self.figure.subplots_adjust(left=0.15, bottom=0.15)
		self.canvas.draw()
		self.starttime = time.time()
		self.timer = wx.Timer(self, id=102)
		self.timer.Start(1000)
		self.Bind(wx.EVT_TIMER, self.ElapsedTime, id=102)
		#self.im.set_data(self.data)
		#self.Update(None,0,noline=True)
	
	def _set_layout(self,addlabels=None):
		panel_b = wx.Panel(self, -1)
		#panel_c = wx.Panel(self, -1)
		#panel_c.SetMinSize((127, 27))
		sizer = wx.FlexGridSizer(2, 1, 0, 0)
		sizer.AddGrowableRow(1,1)
		sizer.AddGrowableCol(0,1)
		sizer.Add(self.toolbar, 1, wx.ADJUST_MINSIZE, 0)
		sizer.Add(self.canvas, 1, wx.GROW, 0)
		#sizer.Add(panel_c, 0, wx.GROW, 0)
		sizer2 = wx.BoxSizer(wx.VERTICAL)
		sizer3 = wx.BoxSizer(wx.VERTICAL)
		sizer4 = wx.BoxSizer(wx.HORIZONTAL)
		padj = wx.StaticBox(self, -1, 'Plot Adjustments')
		self.colors = wx.Choice(self, -1, choices=['-Colors-']+self.cmap.keys())
		self.colors.SetStringSelection(ws.DEFAULT_CMAP)
		self.colinv = wx.CheckBox(self, -1, 'Inv')
		self.interp = wx.Choice(self, -1, choices=self.interps)
		self.colors.SetMinSize((85,27))
		self.colinv.SetMinSize((42,27))
		self.interp.SetMinSize((127,27))
		#sizercol = wx.BoxSizer(wx.HORIZONTAL)
		sizercol = wx.FlexGridSizer(1, 2, 0, 0)
		sizercol.Add(self.colors, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizercol.Add(self.colinv, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2a = wx.StaticBoxSizer(padj,wx.VERTICAL)
		#sizer2a.Add(self.colors, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2a.Add(sizercol, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2a.Add(self.interp, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		#iadj = wx.StaticBox(self, -1,'Interp Tuning')
		#fradsizer = wx.BoxSizer(wx.HORIZONTAL)
		#frad_label = wx.StaticText(self,-1,'Radius')
		#self.frad = wx.SpinCtrl(self, -1, '1', min=1, max=5000)
		#frad_label.SetMinSize((63,27))
		#self.frad.SetMinSize((63,27))
		#fradsizer.Add(frad_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		#fradsizer.Add(self.frad, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		#pixsizer = wx.BoxSizer(wx.HORIZONTAL)
		#pix_label = wx.StaticText(self,-1,'Pixels:')
		#self.pix = wx.StaticText(self, -1, '0.1')
		#self.setrad = wx.Button(self, -1, 'Set Radius')
		#pix_label.SetMinSize((63,27))
		#self.pix.SetMinSize((63,27))
		#self.setrad.SetMinSize((127,27))
		#pixsizer.Add(pix_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		#pixsizer.Add(self.pix, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		#sizer2b = wx.StaticBoxSizer(iadj,wx.VERTICAL)
		#sizer2b.Add(fradsizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		#sizer2b.Add(pixsizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		#sizer2b.Add(self.setrad, 0, wx.ADJUST_MINSIZE, 0)
		

		filt = wx.StaticBox(self, -1,'Filters/Gradients')
		sizer2b = wx.StaticBoxSizer(filt,wx.VERTICAL)
		self.filters = wx.Choice(self, -1, choices=['--Filters--','Gaussian','Uniform','Rank','Maximum','Median','Minimum','Laplace','Sobel','Gaussian Laplace'])
		self.filters.SetMinSize((127,27))
		filtbuttonsizer = wx.BoxSizer(wx.HORIZONTAL)
		self.applyfilter = wx.Button(self, -1, 'Apply')
		self.applyfilter.SetMinSize((63,27))
		self.filtreset = wx.Button(self, -1, 'Reset')
		self.filtreset.SetMinSize((63,27))
		filtbuttonsizer.Add(self.applyfilter, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		filtbuttonsizer.Add(self.filtreset, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)

		fradsizer = wx.BoxSizer(wx.HORIZONTAL)
		frad_label = wx.StaticText(self,-1,'Radius')
		self.frad = wx.SpinCtrl(self, -1, '1', min=1, max=5000)
		frad_label.SetMinSize((63,27))
		self.frad.SetMinSize((63,27))
		fradsizer.Add(frad_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		fradsizer.Add(self.frad, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		pixsizer = wx.BoxSizer(wx.HORIZONTAL)
		pix_label = wx.StaticText(self,-1,'Pixels:')
		self.pix = wx.StaticText(self, -1, '0.1')
		pix_label.SetMinSize((63,27))
		self.pix.SetMinSize((63,27))
		pixsizer.Add(pix_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		pixsizer.Add(self.pix, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)

		sizer2b.Add(self.filters, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2b.Add(fradsizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2b.Add(pixsizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2b.Add(filtbuttonsizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 2)
		#sizer2b.Add(self.setrad, 0, wx.ADJUST_MINSIZE, 0)

		#bkg = wx.StaticBox(self, -1,'Background')
		#backgrounds = ['--Background--','None']+copy(self.frame.pages.keys())
		#self.bkim_box = wx.Choice(self, -1, choices=backgrounds)
		#alphasizer = wx.BoxSizer(wx.HORIZONTAL)
		#alpha_label = wx.StaticText(self,-1,'Alpha%')
		#self.alpha = wx.SpinCtrl(self, -1, '1', min=1, max=100)
		#alpha_label.SetMinSize((63,27))
		#self.alpha.SetMinSize((63,27))
		#alphasizer.Add(alpha_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		#alphasizer.Add(self.alpha, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		#setalpha = wx.Button(self, -1, 'Set Alpha')
		#setalpha.SetMinSize((127,27))
		#self.bkim_box.SetMinSize((127,27))
		#sizer2c = wx.StaticBoxSizer(bkg,wx.VERTICAL)
		#sizer2c.Add(self.bkim_box, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		#sizer2c.Add(alphasizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		#sizer2c.Add(setalpha, 0, wx.ADJUST_MINSIZE, 0)
		#self.bkim_box.Disable()
		#setalpha.Disable()
		#self.alpha.Disable()
		
		prof = wx.StaticBox(self, -1,'Profiles')
		profiles = ['--Profiles--','Vertical','Horizontal','Arbitrary']
		self.prof_box = wx.Choice(self, -1, choices=profiles)
		#alphasizer = wx.BoxSizer(wx.HORIZONTAL)
		#alpha_label = wx.StaticText(self,-1,'Alpha%')
		#self.alpha = wx.SpinCtrl(self, -1, '1', min=1, max=100)
		#alpha_label.SetMinSize((63,27))
		#self.alpha.SetMinSize((63,27))
		#alphasizer.Add(alpha_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		#alphasizer.Add(self.alpha, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		selprof = wx.Button(self, -1, 'Select Profile')
		selprof.SetMinSize((127,27))
		self.selprof=selprof
		self.prof_box.SetMinSize((127,27))
		sizer2c = wx.StaticBoxSizer(prof,wx.VERTICAL)
		sizer2c.Add(self.prof_box, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		#sizer2c.Add(alphasizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2c.Add(selprof, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		#self.prof_box.Disable()
		#setalpha.Disable()
		#self.alpha.Disable()
		
		prog = wx.StaticBox(self, -1, 'Progress')
		self.gauge = wx.Gauge(self, -1, self.shape[0]-1,name='Progress..')
		progsizer = wx.BoxSizer(wx.HORIZONTAL)
		self.elapsedtime = wx.StaticText(self,-1,'Elapsed Time')
		self.displayprop = wx.Button(self, -1, 'Properties')
		self.expimage = wx.Button(self, -1, 'Export to LaTeX')
		self.elapsedtime.SetMinSize((127,27))
		self.gauge.SetMinSize((127,27))
		self.displayprop.SetMinSize((127,27))
		self.expimage.SetMinSize((127,27))
		sizer2d = wx.StaticBoxSizer(prog,wx.VERTICAL)
		sizer2d.Add(self.gauge, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT|wx.TOP, 5)
		sizer2d.Add(self.elapsedtime, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2d.Add(self.displayprop, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2d.Add(self.expimage, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		
		savgol = wx.StaticBox(self, -1, 'Savitzky-Golay')
		savsizer = wx.BoxSizer(wx.HORIZONTAL)
		sgptssizer = wx.BoxSizer(wx.HORIZONTAL)
		sgpts_label = wx.StaticText(self,-1,'# Points:')
		self.sgpts = wx.SpinCtrl(self, -1, str(self.gradpts), min=1, max=30)
		sgpts_label.SetMinSize((63,27))
		self.sgpts.SetMinSize((63,27))
		sgptssizer.Add(sgpts_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		sgptssizer.Add(self.sgpts, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		pordersizer = wx.BoxSizer(wx.HORIZONTAL)
		porder_label = wx.StaticText(self,-1,'PolyOrder:')
		self.porder = wx.SpinCtrl(self, -1, str(self.polyorder), min=1, max=5)
		porder_label.SetMinSize((63,27))
		self.porder.SetMinSize((63,27))
		pordersizer.Add(porder_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		pordersizer.Add(self.porder, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		dordersizer = wx.BoxSizer(wx.HORIZONTAL)
		dorder_label = wx.StaticText(self,-1,'DerivOrder:')
		self.dorder = wx.SpinCtrl(self, -1, str(self.sgderiv), min=0, max=5)
		dorder_label.SetMinSize((63,27))
		self.dorder.SetMinSize((63,27))
		dordersizer.Add(dorder_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		dordersizer.Add(self.dorder, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		self.sgupdate = wx.Button(self, -1, 'Apply')
		self.sgupdate.SetMinSize((127,27))
		self.sgclear = wx.Button(self, -1, 'Clear')
		self.sgclear.SetMinSize((127,27))
		sizer2f = wx.StaticBoxSizer(savgol,wx.VERTICAL)
		sizer2f.Add(sgptssizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(pordersizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(dordersizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(self.sgupdate, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(self.sgclear, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		fftbox = wx.StaticBox(self, -1, 'FFT/Filter')
		self.fftlog = wx.CheckBox(self, -1, label='Log Display')
		self.showfft = wx.ToggleButton(self, -1, 'Twin View')
		self.APPLY_ID = wx.NewId()
		self.applyfft = wx.Button(self, self.APPLY_ID, 'Apply')
		self.clearfft = wx.Button(self, -1, 'Clear')
		padtxt = wx.StaticText(self,-1,'Pad 0s')
		self.padval=wx.SpinCtrl(self,-1,'0',min=0,max=1000)
		self.windowfft=wx.Choice(self,-1,choices=('None','hanning','hamming','bartlett','blackman'))
		self.maskfft=wx.Choice(self,-1,choices=('Square','4-Fold','4-Fold Inverse','6-Fold','6-Fold Inverse'))
		self.selectmaskfft=wx.Button(self,-1,'Select')
		self.filterfft=wx.Button(self,-1,'Filter')
		self.clearfilterfft=wx.Button(self,-1,'Clear')
		filterpixtxt=wx.StaticText(self,-1,'Pixels')
		self.filterpix=wx.SpinCtrl(self,-1,'1',min=1,max=100)
		fftsizer = wx.BoxSizer(wx.HORIZONTAL)
		fftsizer2 = wx.BoxSizer(wx.HORIZONTAL)
		fftsizer3 = wx.BoxSizer(wx.HORIZONTAL)
		fftsizer4 = wx.BoxSizer(wx.HORIZONTAL)
		fftsizer5 = wx.BoxSizer(wx.HORIZONTAL)
		self.fftlog.SetMinSize((127,27))
		self.showfft.SetMinSize((127,27))
		self.windowfft.SetMinSize((127,27))
		self.maskfft.SetMinSize((62,27))
		self.selectmaskfft.SetMinSize((62,27))
		self.applyfft.SetMinSize((62,27))
		self.clearfft.SetMinSize((62,27))
		self.filterfft.SetMinSize((62,27))
		self.clearfilterfft.SetMinSize((62,27))
		self.filterfft.Disable()
		self.filterpix.Disable()
		self.selectmaskfft.Disable()
		self.maskfft.Disable()
		fftsizer2.Add(self.applyfft, 0, wx.ADJUST_MINSIZE|wx.RIGHT, 2)
		fftsizer2.Add(self.clearfft, 0, wx.ADJUST_MINSIZE|wx.LEFT, 1)
		fftsizer3.Add(self.filterfft, 0, wx.ADJUST_MINSIZE|wx.RIGHT, 2)
		fftsizer3.Add(self.clearfilterfft, 0, wx.ADJUST_MINSIZE|wx.LEFT, 1)
		fftsizer5.Add(self.selectmaskfft, 0, wx.ADJUST_MINSIZE|wx.RIGHT, 2)
		fftsizer5.Add(self.maskfft, 0, wx.ADJUST_MINSIZE|wx.LEFT, 1)
		padtxt.SetMinSize((57,27))
		self.padval.SetMinSize((62,27))
		fftsizer.Add(padtxt, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		fftsizer.Add(self.padval, 0, wx.ADJUST_MINSIZE|wx.LEFT, 1)
		filterpixtxt.SetMinSize((57,27))
		self.filterpix.SetMinSize((62,27))
		fftsizer4.Add(filterpixtxt, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		fftsizer4.Add(self.filterpix, 0, wx.ADJUST_MINSIZE|wx.LEFT, 1)
		sizer2g = wx.StaticBoxSizer(fftbox,wx.VERTICAL)
		sizer2g.Add(self.fftlog, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(self.showfft, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(self.windowfft, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(fftsizer, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(fftsizer2, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(fftsizer5, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(fftsizer4, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(fftsizer3, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		subtr = wx.StaticBox(self, -1, 'Subtraction')
		self.subtr = wx.Choice(self, -1, choices=['--Subtraction--','None','Line','Plane'])
		self.showhist = wx.Button(self, -1, 'Show Histogram')
		progsizer = wx.BoxSizer(wx.HORIZONTAL)
		self.subtr.SetMinSize((127,27))
		self.showhist.SetMinSize((127,27))
		sizer2e = wx.StaticBoxSizer(subtr,wx.VERTICAL)
		sizer2e.Add(self.subtr, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2e.Add(self.showhist, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2a, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2e, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2b, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2f, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		#sizer2.Add(sizer2g, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2c, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2d, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(panel_b, 1, wx.EXPAND, 0)
		
		unitbox = wx.StaticBox(self, -1, 'Units')
		unit_types = ['XY','Z','I']
		self.unit_type = wx.Choice(self, -1, choices=unit_types)
		self.use_unit = wx.Choice(self, -1, choices=self.dist_unit)
		#self.unit_apply = wx.Button(self, -1, 'Apply')
		self.show_scale = wx.Choice(self, -1, choices=['0','25','50','75','100'])
		self.show_scale.Disable()
		showscaletext = wx.StaticText(self,-1,'Alpha')
		self.scale_colorR = wx.Choice(self, -1, choices=['R','0','2','4','6','8','a','c','e'])
		self.scale_colorG= wx.Choice(self, -1, choices=['G','0','2','4','6','8','a','c','e'])
		self.scale_colorB= wx.Choice(self, -1, choices=['B','0','2','4','6','8','a','c','e'])
		unitsizer1 = wx.BoxSizer(wx.HORIZONTAL)
		unitsizer2 = wx.BoxSizer(wx.HORIZONTAL)
		self.unit_type.SetMinSize((127,27))
		self.use_unit.SetMinSize((127,27))
		#self.unit_apply.SetMinSize((127,27))
		showscaletext.SetMinSize((57,27))
		self.show_scale.SetMinSize((62,27))
		self.scale_colorR.SetMinSize((44,27))
		self.scale_colorG.SetMinSize((44,27))
		self.scale_colorB.SetMinSize((44,27))
		unitsizer1.Add(showscaletext, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		unitsizer1.Add(self.show_scale, 0, wx.ADJUST_MINSIZE|wx.LEFT, 1)
		unitsizer2.Add(self.scale_colorR, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.TOP, 0)
		unitsizer2.Add(self.scale_colorG, 0, wx.ADJUST_MINSIZE|wx.TOP, 0)
		unitsizer2.Add(self.scale_colorB, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 0)
		sizer3a = wx.StaticBoxSizer(unitbox,wx.VERTICAL)
		sizer3a.Add(self.unit_type, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3a.Add(self.use_unit, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		#sizer3a.Add(self.unit_apply, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3a.Add(unitsizer1, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3a.Add(unitsizer2, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		multibox = wx.StaticBox(self, -1, 'Layer/Direction')
		self.bias_layer = wx.Choice(self, -1, choices=[])
		self.disp_direc = wx.Choice(self, -1, choices=['Forward','Reverse'])
		self.bias_layer.Disable()
		self.disp_direc.Disable()
		multisizer = wx.BoxSizer(wx.HORIZONTAL)
		self.bias_layer.SetMinSize((127,27))
		self.disp_direc.SetMinSize((127,27))
		sizer3b = wx.StaticBoxSizer(multibox,wx.VERTICAL)
		sizer3b.Add(self.bias_layer, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3b.Add(self.disp_direc, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		contbox = wx.StaticBox(self, -1, 'Contours')
		cspace_label = wx.StaticText(self,-1,'N Contours:')
		self.cspace = wx.SpinCtrl(self, -1, '2', min=2, max=50)
		self.showcont = wx.ToggleButton(self, -1, 'Show Contours')
		self.cspace.Disable()
		self.showcont.Disable()
		#self.cspace.Disable()
		#self.showcont.Disable()
		self.showcont.SetMinSize((127,27))
		cspace_label.SetMinSize((79,27))
		self.cspace.SetMinSize((43,27))
		cspacesizer = wx.BoxSizer(wx.HORIZONTAL)
		cspacesizer.Add(cspace_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 10)
		cspacesizer.Add(self.cspace, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		sizer3c = wx.StaticBoxSizer(contbox,wx.VERTICAL)
		sizer3c.Add(cspacesizer, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3c.Add(self.showcont, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)

		#closebox = wx.StaticBox(self, -1, 'Close Page')
		#self.close_this = wx.Button(self, -1, 'Close')
		##closesizer = wx.BoxSizer(wx.HORIZONTAL)
		#self.close_this.SetMinSize((127,27))
		#sizer3d = wx.StaticBoxSizer(closebox,wx.VERTICAL)
		#sizer3d.Add(self.close_this, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)

		closebox = wx.StaticBox(self, -1, 'Close/Mark Page')
		self.mark_this = wx.Button(self, -1, 'Mark')
		self.unmark_this = wx.Button(self, -1, 'Unmark')
		self.close_this = wx.Button(self, -1, 'Close')
		#closesizer = wx.BoxSizer(wx.HORIZONTAL)
		sizermark = wx.BoxSizer(wx.HORIZONTAL)
		self.mark_this.SetMinSize((62,27))
		self.unmark_this.SetMinSize((62,27))
		sizermark.Add(self.mark_this, 0, wx.ADJUST_MINSIZE|wx.RIGHT, 5)
		sizermark.Add(self.unmark_this, 0, wx.ADJUST_MINSIZE|wx.LEFT, 5)
		self.close_this.SetMinSize((127,27))
		sizer3d = wx.StaticBoxSizer(closebox,wx.VERTICAL)
		sizer3d.Add(sizermark, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3d.Add(self.close_this, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		self.close_this.Bind(wx.EVT_BUTTON, self.delFromNotebook)
		self.mark_this.Bind(wx.EVT_BUTTON, self.MarkOffset)
		self.unmark_this.Bind(wx.EVT_BUTTON, self.UnmarkOffset)

		sizer3.Add(sizer3a, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3.Add(sizer3b, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3.Add(sizer3c, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3.Add(sizer2g, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3.Add(sizer3d, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer4.Add(sizer2, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer4.Add(sizer3, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		if addlabels != None:
			grid_sizer_1 = wx.FlexGridSizer(1, 3, 0, 0)
			grid_sizer_1.AddGrowableRow(0,1)
			grid_sizer_1.AddGrowableCol(0,1)
			grid_sizer_1.Add(sizer, 1, wx.GROW, 0)
			grid_sizer_1.Add(sizer2, 1, wx.GROW, 0)
			grid_sizer_1.Add(addlabels, 1, wx.GROW, 0)
		else:
			grid_sizer_1 = wx.FlexGridSizer(1, 2, 0, 0)
			grid_sizer_1.AddGrowableRow(0,1)
			grid_sizer_1.AddGrowableCol(0,1)
			grid_sizer_1.Add(sizer, 1, wx.GROW, 0)
			grid_sizer_1.Add(sizer4, 1, wx.GROW, 0)
		self.SetSizer(grid_sizer_1)
		self.canvas.mpl_connect('motion_notify_event', self.frame.UpdateStatusBar)
		#self.canvas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor)
		self.colors.Bind(wx.EVT_CHOICE, self.OnColor)
		self.interp.Bind(wx.EVT_CHOICE, self.OnInterp)
		self.showhist.Bind(wx.EVT_BUTTON, self.OnHist)
		self.subtr.Bind(wx.EVT_CHOICE, self.OnSubtr)
		self.sgupdate.Bind(wx.EVT_BUTTON, self.OnSGUp)
		self.sgclear.Bind(wx.EVT_BUTTON, self.OnSGClear)
		self.frad.Bind(wx.EVT_SPINCTRL, self.OnFrad)
		self.applyfilter.Bind(wx.EVT_BUTTON, self.OnFilter)
		self.filtreset.Bind(wx.EVT_BUTTON,self.OnFReset)
		#self.setrad.Bind(wx.EVT_BUTTON, self.SetFrad)
		self.colinv.Bind(wx.EVT_CHECKBOX, self.OnInv)
		self.applyfft.Bind(wx.EVT_BUTTON, self.OnFFT)
		self.showfft.Bind(wx.EVT_TOGGLEBUTTON,self.OnShowFFT)
		self.filterfft.Bind(wx.EVT_BUTTON,self.OnFilterFFT)
		self.maskfft.Bind(wx.EVT_CHOICE,self.OnMaskSwitch)
		self.clearfilterfft.Bind(wx.EVT_BUTTON,self.OnClearFilterFFT)
		self.selectmaskfft.Bind(wx.EVT_BUTTON,self.OnSelMask)
		self.clearfft.Bind(wx.EVT_BUTTON,self.OnClearFFT)
		self.fftlog.Bind(wx.EVT_CHECKBOX, self.OnFFTLog)
		self.unit_type.Bind(wx.EVT_CHOICE, self.OnUType)
		self.use_unit.Bind(wx.EVT_CHOICE, self.OnUApply)
		self.showcont.Bind(wx.EVT_TOGGLEBUTTON, self.OnShowCont)
		self.disp_direc.Bind(wx.EVT_CHOICE, self.OnDirection)
		self.bias_layer.Bind(wx.EVT_CHOICE, self.OnDirection)
		self.show_scale.Bind(wx.EVT_CHOICE, self.OnShowScale)
		self.scale_colorR.Bind(wx.EVT_CHOICE, self.OnScaleColor)
		self.scale_colorG.Bind(wx.EVT_CHOICE, self.OnScaleColor)
		self.scale_colorB.Bind(wx.EVT_CHOICE, self.OnScaleColor)
		self.displayprop.Bind(wx.EVT_BUTTON, self.OnDispProp)
		self.expimage.Bind(wx.EVT_BUTTON, self.OnExportImage)
		self.close_this.Bind(wx.EVT_BUTTON, self.delFromNotebook)
		self.displayprop.Disable()
		#self.setrad.Bind(wx.EVT_BUTTON, self.look3D)
		#norm.Bind(wx.EVT_CHOICE, self.OnNorm)
		#self.bkim_box.Bind(wx.EVT_CHOICE, self.OnBackground)
		selprof.Bind(wx.EVT_BUTTON, self.OnProfile)
		#setalpha.Bind(wx.EVT_BUTTON, self.SetAlpha)

	def MarkOffset(self,event):
		if hasattr(self,'package'):
			if hasattr(self.package,'YOFF'): yoff = self.package.YOFF[0]
			if hasattr(self.package, 'XOFF'): xoff = self.package.XOFF[0]
			if hasattr(self.package, 'PHYS_X'): width = self.package.PHYS_X[0]
			if hasattr(self.package, 'PHYS_Y'): height = self.package.PHYS_Y[0]
			if hasattr(self,'offrect'): self.offrect.remove()
			self.offrect = matplotlib.patches.Rectangle((xoff-(width/2.),yoff-(height/2.)), width, height, facecolor='w', edgecolor='#aaaaaa',lw=1.5)
			self.frame.offsetfig.gca().add_patch(self.offrect)
			self.frame.offsetcanvas.draw()
	
	def UnmarkOffset(self,event):
		if hasattr(self,'offrect'): 
			self.offrect.remove()
			delattr(self,'offrect')
			self.frame.offsetcanvas.draw()

	def OnDispProp(self,event):
		if hasattr(self,'package'):
			if hasattr(self.package,'SCAN_NUMBER'): namestr = self.package.SCAN_NUMBER
			elif hasattr(self.package, 'SCAN'): namestr = self.package.SCAN
			else: namestr = ''
			ScanProperties(self,self.package,namestr)

	def OnExportImage(self,event):
		if hasattr(self,'package') and hasattr(self.package,'SCAN_NUMBER'):
			fullpath=self.imagepath+str(self.package.SCAN_NUMBER)+'.png'
			count=0
			while os.path.exists(fullpath):
				count+=1
				fullpath=self.imagepath+str(self.package.SCAN_NUMBER)+'_%d.png'%count
			self.figure.savefig( fullpath, format='png' )
			self.editor.InsertImage(fullpath,str(self.package.SCAN_NUMBER))
		else:
			fullpath=self.imagepath+'XXXXXXXXXX'+'.png'
			self.figure.savefig( fullpath, format='png' )
			self.editor.InsertImage(fullpath,'XXXXXXXXXX')

	def OnDirection(self,event):
		if hasattr(self,'data_full'):
			try:
				self.mblayer = self.bias_layer.GetSelection()
				#self.mblayer = int(str(self.bias_layer.GetStringSelection())[-1:])
			except: self.mblayer = 0
			if str(self.disp_direc.GetStringSelection()) == 'Forward':
				self.direc = 0
				self.data = self.data_full[self.mblayer][self.direc]
			else:
				self.direc = 1
				self.data = self.data_full[self.mblayer][self.direc]
			self.display = deepcopy(self.data)
			self.OnSubtr(None)
		else: print 'no data_full attribute'
	
	def OnShowCont(self,event):
		if self.showcont.GetValue():
			ncurves = int(self.cspace.GetValue())
			if ncurves == 1: levels = [self.display.mean()]
			else:
				step = (self.display.max()-self.display.min())/ncurves
				avg = self.display.mean()
				start = avg-(ncurves-1)*(step/2.)-0.01
				end = avg+(ncurves-1)*(step/2.)+0.01
				levels = n.arange(start, end, step)
			self.CS = self.subplot.contour(self.display,levels,origin='lower',linewidths=2,alpha=0.33)
			self.contours = self.subplot.clabel(self.CS,inline=0,fmt='%1.1f',fontsize=12)
		else:
			if hasattr(self,'CS'):
				self.ReDraw(colorbar=False)
		self.canvas.draw()
	
	def ReDraw(self,twin=False,scale=True,colorbar=True):
		self.subplot.clear()
		if not twin: twin=self.showfft.GetValue()
		#if self.extent:
			#self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			#interpolation=self.currinterp)
			#if not twin:
				#self.colorbar = self.figure.colorbar(self.im,shrink=0.8)
				#self.colorbar.draw_all()
				#self.subplot.set_title('Scan No. '+self.SCAN)
		#else:
		self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
		interpolation=self.currinterp)
		self.subplot.set_xlabel('X (Pixels)')
		self.subplot.set_ylabel('Y (Pixels)')
		if not twin:
			if colorbar:
				self.colorbar = self.figure.colorbar(self.im,shrink=0.8)
				self.colorbar.draw_all()
			self.subplot.set_title('Scan No. '+self.SCAN)
			self.scalebar=[None,None]
		if scale: self.MakeScaleBar()
	
	def OnUType(self,event):
		unit = str(self.unit_type.GetStringSelection())
		if unit == 'XY' or unit == 'Z':
			self.use_unit.SetItems(self.dist_unit)
		elif unit == 'I':
			self.use_unit.SetItems(self.current_unit)
	
	def OnUApply(self,event):
		unittype = str(self.unit_type.GetStringSelection())
		unit = str(self.use_unit.GetStringSelection())
		if unittype == 'XY':
			self.xyunit = unit
			self.MakeScaleBar()
		elif unittype == 'Z':
			self.zunit = unit
			self.OnSubtr(None)
		elif unittype == 'I': self.iunit = unit
		#self.OnSubtr(None)
		
	
	def addToNotebook(self,title):
		self.parent.AddPage(self,title)
		self.SCAN = title
		self.parent.SetSelection(self.pagenum)
	
	def delFromNotebook(self,event): self.parent.RemovePage(self.parent.GetSelection())
		
	def subtr1Line(self,line):
		X = n.zeros(line.shape)
		X[:] = range(len(line[0]))
		a,b = self.linreg(X,line)
		subtr = n.add(n.multiply(X[0],a[0]),b[0])
		line2 = n.subtract(copy(line),subtr)
		return line2
	
	def linreg(self, X1, Y1, image=False):
		"""
		Takes two matricies and finds the slope and intercept of each line
		along axis 1.
		
		Returns 2 arrays. b is the array of intercepts and a
		is the array of slopes.
		"""
		if X1.shape != Y1.shape:  raise ValueError, 'unequal length'
		if not image:
			X = X1[::5]
			Y = Y1[::5]
		else:
			X = X1
			Y = Y1
		N = len(X[0])
		Sx = Sy = Sxx = Syy = Sxy = n.zeros(N)
		Sx = n.sum(X,axis=1)
		Sy = n.sum(Y,axis=1)
		Sxx = n.sum(n.square(X),axis=1)
		Syy = n.sum(n.square(Y),axis=1)
		
		Sxy = n.sum(n.multiply(X,Y),axis=1)
		det = n.subtract(n.multiply(Sxx,N),n.square(Sx))
		a, b = n.divide(n.subtract(n.multiply(Sxy,N),n.multiply(Sy,Sx)),det),\
		n.divide(n.subtract(n.multiply(Sxx,Sy),n.multiply(Sx,Sxy)),det)
		return a,b
	
	def subtr1Plane(self,line,lineN):
		X = n.zeros(line.shape)
		X[:] = range(len(line[0]))
		
		subtr = n.multiply(X[0],self.ax)+lineN*self.ay
		line2 = n.subtract(copy(line),subtr)-self.pave
		return line2
	
	def savgolXLine(self,line):
		data2 = n.zeros(line.shape)
		data2 = n.array([sg.smooth(copy(line[0]),self.coeff)])
		return data2
	
	def subtrImageLines(self,data):
		fits = []
		X = n.zeros(n.shape(data))
		for i in range(n.shape(data)[1]):
			X[:,i] = i
		Y = data
		fits = self.linreg(X,Y,image=True)
		subtr = n.transpose(n.add(n.multiply(n.transpose(X),fits[0]),fits[1]))
		data2 = n.subtract(data,subtr)
		return data2
		
	def subtrImagePlane(self,data1,lineN):
		data = deepcopy(data1)[0:lineN,:]
		Xx = n.zeros(n.shape(data))
		for i in range(n.shape(data)[1]):
			Xx[:,i] = i
		Yx = data
		ax,bx = self.linreg(Xx,Yx,image=True)

		Xy = n.zeros(n.shape(data))
		for i in range(n.shape(data)[0]):
			Xy[i,:] = i
		Yy = data
		ay,by = self.linreg(n.transpose(Xy),n.transpose(Yy),image=True)
		self.ax = n.average(ax)
		self.ay = n.average(ay)
		subtrx = n.multiply(Xx,self.ax)
		subtry = n.multiply(Xy,self.ay)
		subtr = n.add(subtrx,subtry)
		sdata = n.subtract(deepcopy(data),subtr)
		self.pave = n.average(sdata)
		sdata = n.subtract(sdata,self.pave)
		rdata = n.zeros(data1.shape)
		rdata[0:lineN,:] = sdata
		return rdata
	
	def savgolX(self,data):
		data2 = n.zeros(data.shape)
		if self.sgderiv > self.polyorder:
			self.porder.SetValue(int(self.sgderiv))
			self.polyorder = self.sgderiv
		self.coeff = sg.calc_coeff(self.gradpts, self.polyorder, self.sgderiv)
		for i in range(data.shape[0]): data2[i] = sg.smooth(data[i],self.coeff)
		return data2
	
	def FFT2d(self,data):
		pad=int(self.padval.GetValue())
		window=self.windowfft.GetStringSelection()
		if window=='hanning':
			windvals=(n.resize(n.hanning(data.shape[0]),(data.shape[0],1))*n.resize(n.hanning(data.shape[1]),(1,data.shape[1])))
		elif window=='hamming':
			windvals=(n.resize(n.hamming(data.shape[0]),(data.shape[0],1))*n.resize(n.hamming(data.shape[1]),(1,data.shape[1])))
		elif window=='blackman':
			windvals=(n.resize(n.blackman(data.shape[0]),(data.shape[0],1))*n.resize(n.blackman(data.shape[1]),(1,data.shape[1])))
		elif window=='kaiser':
			windvals=(n.resize(n.kaiser(data.shape[0],beta=0),(data.shape[0],1))*n.resize(n.kaiser(data.shape[1],beta=0),(1,data.shape[1])))
		elif window=='bartlett':
			windvals=(n.resize(n.bartlett(data.shape[0]),(data.shape[0],1))*n.resize(n.bartlett(data.shape[1]),(1,data.shape[1])))
		else: windvals=n.ones(data.shape)
		fft_data = n.fft.fft2(windvals*deepcopy(data),s=(data.shape[0]+pad,data.shape[1]+pad))
		self.fft_raw=n.roll(n.roll(fft_data,(data.shape[0]+pad)/2,axis=0),(data.shape[1]+pad)/2,axis=1)
		fft_mod = n.sqrt(n.real(fft_data)**2+n.imag(fft_data)**2)
		fft_roll = n.roll(n.roll(fft_mod,(data.shape[0]+pad)/2,axis=0),(data.shape[1]+pad)/2,axis=1)
		if self.fftlog.GetValue():
			fft_roll += 0.0001*(fft_roll.max()-fft_roll.min())
			return n.log(fft_roll)
		else: return fft_roll
	
	
	def displayConvert(self,data,image=False):
		subtype = str(self.subtr.GetStringSelection())
		if not image:
			if subtype == 'None' or subtype == '--Subtraction--': data2 = data
			elif subtype == 'Line': data2 = self.subtr1Line(deepcopy(data))
			elif subtype == 'Plane': data2 = self.subtr1Plane(deepcopy(data),self.lineN)
			else: data2 = data
		else:
			if subtype == 'None' or subtype == '--Subtraction--': data2 = data
			elif subtype == 'Line': data2 = self.subtrImageLines(deepcopy(data))
			elif subtype == 'Plane': data2 = self.subtrImagePlane(deepcopy(data),self.lineN)
			else: data2 = data
		if hasattr(self,'UO'):
			unit_type=self.unit_type.GetStringSelection()
			if unit_type=='Z':
				if hasattr(self,'package'):
					data2 = self.UO._ConvertZScale(data2,self.UO.ZVOLTS,self.UO.units[self.zunit][0],self.package.GAIN_ZHV[0],self.package.GAIN_ZOUT[0])
				else:
					data2 = self.UO._ConvertZScale(data2,self.UO.ZVOLTS,self.UO.units[self.zunit][0],self.ZHV,self.ZOUT)
			elif unit_type=='XY' and hasattr(self,'package'):
				if not hasattr(self,'scalebar') or self.scalebar[0] == None:
					self.MakeScaleBar()
		return data2
	
	def OnShowScale(self,event,draw=True):
		alpha=self.show_scale.GetStringSelection()
		if hasattr(self.scalebar[1],'set_alpha'): self.scalebar[1].set_alpha(float(alpha)/100.)
		if hasattr(self.scalebar[0],'set_alpha'): self.scalebar[0].set_alpha(float(alpha)/100.)
		if draw: self.canvas.draw()
		self.scale_trans=float(alpha)/100.
	
	def OnScaleColor(self,event,draw=True):
		colorR=self.scale_colorR.GetStringSelection()
		colorG=self.scale_colorG.GetStringSelection()
		colorB=self.scale_colorB.GetStringSelection()
		if colorR[0]=='R': colorR='0'
		if colorG[0]=='G': colorG='0'
		if colorB[0]=='B': colorB='0'
		color='#'+2*colorR+2*colorG+2*colorB
		if hasattr(self.scalebar[1],'set_color'): self.scalebar[1].set_color(color)
		if hasattr(self.scalebar[0],'set_color'): self.scalebar[0].set_color(color)
		if draw: self.canvas.draw()

	def MakeScaleBar(self):
		if hasattr(self,'package'):
			xext,yext=self.UO._ConvertPixels(self.data.shape[0],self.data.shape[1],self.package.DAC_STEP[0]*self.package.DAC_AVGS[0],\
			self.UO.units[self.xyunit][0],self.package.GAIN_XHV[0],self.package.GAIN_YHV[0])
		elif hasattr(self,'DAC_STEP'):
			xext,yext=self.UO._ConvertPixels(self.data.shape[0],self.data.shape[1],self.DAC_STEP[0]*self.DAC_AVGS[0],\
			self.UO.units[self.xyunit][0],1,1)
		else: yext,xext = self.data.shape
		self.extents=(xext,yext)
		if not self.scalebar[1] == None:
			self.scalebar[1].set_text('%.2f %s'%((self.extents[0]/5.),self.UO.units[self.xyunit][1]))
		else:
			self.scalebar[0]=self.subplot.axhline(y=int(self.data.shape[1]*0.1), xmin=0.05, xmax=0.25,linewidth=4, color='r')
			self.scalebar[1]=self.subplot.text(int(self.data.shape[0]*0.22/2),int(self.data.shape[1]*0.075),'%.2f %s'%((self.extents[0]/5.),\
			self.UO.units[self.xyunit][1]), fontsize=16, color='r')
		#self.scalebar[0].set_alpha(0)
		self.OnShowScale(None,draw=False)
		self.OnScaleColor(None,draw=False)
		self.canvas.draw()

	def OnSubtr(self, event):
		data = self.displayConvert(self.data,image=True)
		self.display = data
		self.im.set_data(self.display)
		self.AutoAdjust()
		#self.im.set_extent(self.extent)
		self.canvas.draw()
	
	def OnShowFFT(self, event):
		if self.showfft.GetValue():
			self.figure.clf()
			self.subplot = self.figure.add_subplot(121)
			self.ReDraw(twin=True)
			self.canvas.draw()
			self.OnSubtr(event)
			self.AutoAdjust()
			self.subplotfft=self.figure.add_subplot(122)
			self.canvas.draw()
			self.OnFFT(event)
			self.filterfft.Enable()
			self.filterpix.Enable()
			self.selectmaskfft.Enable()
			self.maskfft.Enable()
		else:
			self.filterfft.Disable()
			self.filterpix.Disable()
			self.selectmaskfft.Disable()
			self.maskfft.Disable()
			self.figure.clf()
			self.subplot = self.figure.add_subplot(111)
			#self.OnFFT(event)
			self.ReDraw()
			self.canvas.draw()
		self.fftmask=n.zeros(self.fft_raw.shape)
	
	def OnClearFFT(self, event):
		if self.showfft.GetValue(): pass
		else:
			self.OnSubtr(event)
			self.ReDraw(colorbar=False)
			self.canvas.draw()
	
	def OnSelMask(self,event):
		if self.showfft.GetValue():
			self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_QUESTION_ARROW))
			self.canvas.Bind(wx.EVT_LEFT_DOWN, self.MaskFFT)
	
	def OnMaskSwitch(self,event):
		masktype=self.maskfft.GetStringSelection()
		if masktype=='Square': self.fftmask[:,:]=1
		elif masktype=='4-Fold': self.fftmask[:,:]=1
		elif masktype=='4-Fold Inverse': self.fftmask[:,:]=0
		elif masktype=='6-Fold': self.fftmask[:,:]=1
		elif masktype=='6-Fold Inverse': self.fftmask[:,:]=0

	def SqrMask(self,xloc,yloc,pix,inv=False):
		if not inv: self.fftmask[yloc-pix/2:yloc+pix/2,xloc-pix/2:xloc+pix/2]=0
		else: self.fftmask[yloc-pix/2:yloc+pix/2,xloc-pix/2:xloc+pix/2]=1
		el = matplotlib.patches.Rectangle((xloc-pix/2, yloc-pix/2), pix, pix,facecolor='w',edgecolor='w')
		self.subplotfft.add_patch(el)
		el.set_alpha(0.25)

	def MaskFFT(self,event):
		self.canvas.Bind(wx.EVT_LEFT_DOWN, None)
		self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
		xloc = int(round(self.frame.x))
		yloc = int(round(self.frame.y))
		pix=int(self.filterpix.GetValue())
		masktype=self.maskfft.GetStringSelection()
		if masktype=='Square': self.SqrMask(xloc,yloc,pix)
		elif masktype=='4-Fold':
			dx=xloc-self.fft_raw.shape[0]/2
			dy=yloc-self.fft_raw.shape[1]/2
			cx=self.fft_raw.shape[0]/2
			cy=self.fft_raw.shape[1]/2
			self.SqrMask(cx+dx,cy+dy,pix)
			self.SqrMask(cx-dx,cy-dy,pix)
			self.SqrMask(cx-dy,cy+dx,pix)
			self.SqrMask(cx+dy,cy-dx,pix)
		elif masktype=='4-Fold Inverse':
			dx=xloc-self.fft_raw.shape[0]/2
			dy=yloc-self.fft_raw.shape[1]/2
			cx=self.fft_raw.shape[0]/2
			cy=self.fft_raw.shape[1]/2
			self.SqrMask(cx+dx,cy+dy,pix,inv=True)
			self.SqrMask(cx-dx,cy-dy,pix,inv=True)
			self.SqrMask(cx-dy,cy+dx,pix,inv=True)
			self.SqrMask(cx+dy,cy-dx,pix,inv=True)
		elif masktype=='6-Fold':
			dx=xloc-self.fft_raw.shape[0]/2
			dy=yloc-self.fft_raw.shape[1]/2
			cx=self.fft_raw.shape[0]/2
			cy=self.fft_raw.shape[1]/2
			a1=n.sin(60*n.pi/180)
			a2=n.sin(30*n.pi/180)
			self.SqrMask(cx+dx,cy+dy,pix)
			self.SqrMask(cx-dx,cy-dy,pix)
			self.SqrMask(cx+(a2*dx-a1*dy),cy+(a1*dx+a2*dy),pix)
			self.SqrMask(cx-(a2*dx-a1*dy),cy-(a1*dx+a2*dy),pix)
			self.SqrMask(cx+(a2*dx+a1*dy),cy-(a1*dx-a2*dy),pix)
			self.SqrMask(cx-(a2*dx+a1*dy),cy+(a1*dx-a2*dy),pix)
		elif masktype=='6-Fold Inverse':
			dx=xloc-self.fft_raw.shape[0]/2
			dy=yloc-self.fft_raw.shape[1]/2
			cx=self.fft_raw.shape[0]/2
			cy=self.fft_raw.shape[1]/2
			a1=n.sin(60*n.pi/180)
			a2=n.sin(30*n.pi/180)
			self.SqrMask(cx+dx,cy+dy,pix,inv=True)
			self.SqrMask(cx-dx,cy-dy,pix,inv=True)
			self.SqrMask(cx+(a2*dx-a1*dy),cy+(a1*dx+a2*dy),pix,inv=True)
			self.SqrMask(cx-(a2*dx-a1*dy),cy-(a1*dx+a2*dy),pix,inv=True)
			self.SqrMask(cx+(a2*dx+a1*dy),cy-(a1*dx-a2*dy),pix,inv=True)
			self.SqrMask(cx-(a2*dx+a1*dy),cy+(a1*dx-a2*dy),pix,inv=True)
		self.canvas.draw()
	
	def OnFilterFFT(self,event):
		# Re-display Masked Fourier Transform
		#fft_mod = n.sqrt(n.real(self.fft_raw)**2+n.imag(self.fft_raw)**2)
		#if self.fftlog.GetValue():
			#fft_mod += 0.0001*(fft_mod.max()-fft_mod.min())
			#fft_mod=n.log(fft_mod)
		#self.imfft.set_data(fft_mod)

		fft_roll = n.roll(n.roll(self.fftmask*self.fft_raw,(self.fft_raw.shape[0])/2,axis=0),(self.fft_raw.shape[1])/2,axis=1)
		fft_data=n.fft.ifft2(deepcopy(fft_roll),s=(fft_roll.shape[0],fft_roll.shape[1]))
		fft_mod = n.real(fft_data)
		self.display= fft_mod
		self.ReDraw(twin=True)
		self.canvas.draw()
	
	def OnClearFilterFFT(self,event):
		self.OnMaskSwitch(None)
		#self.OnSubtr(event)
		self.ReDraw(colorbar=False)
		if self.showfft.GetValue(): self.OnFFT(event)
	
	def OnMaskFFT(self,event): pass

	def OnFFT(self, event,log=False):
		#if self.applyfft.GetValue():
		if self.showfft.GetValue():
			#twin view on
			self.subplotfft.clear()
			fftdisplay = self.FFT2d(self.display)
			self.imfft=self.subplotfft.imshow(fftdisplay,origin='lower')
			self.canvas.draw()
		else:
			#twin view off
			self.display = self.FFT2d(self.display)
			if event.GetId() == self.APPLY_ID or log: self.ReDraw(scale=False,colorbar=False)
			else: self.ReDraw(scale=False)
			self.canvas.draw()
		#else: self.OnSubtr(event)
	
	def OnFFTLog(self, event):
		#if self.applyfft.GetValue():
		data = self.displayConvert(self.data,image=True)
		self.display = data
		self.OnFFT(event,log=True)
		#else: pass
	
	def OnInv(self, event):
		color = self.colors.GetStringSelection()
		self.OnColor(event,color=color)
	
	def OnProfile(self, event):
		self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_QUESTION_ARROW))
		self.canvas.Bind(wx.EVT_LEFT_DOWN, self.MakeProfile)
	
	def OnSGUp(self, event):
		self.gradpts = int(self.sgpts.GetValue())
		self.polyorder = int(self.porder.GetValue())
		self.sgderiv = int(self.dorder.GetValue())
		data2 = self.savgolX(deepcopy(self.data))
		data=self.displayConvert(data2,image=True)
		self.display=data
		self.im.set_data(self.display)
		self.AutoAdjust()
		self.canvas.draw()
	
	def OnSGClear(self, event):
		self.OnSubtr(event)

	def MakeProfile(self, event):
		xloc = int(round(self.frame.x))
		yloc = int(round(self.frame.y))
		self.canvas.Bind(wx.EVT_LEFT_DOWN, None)
		if not hasattr(self,'extents'):
			self.MakeScaleBar()
		if str(self.prof_box.GetStringSelection()) == 'Vertical':
			if xloc > len(self.display[:,xloc]): pass
			else:
				#self.xline = self.im.axes.axvline(x=xloc,figure=self.figure)
				title = 'Vertical Profile at x=%d'%xloc
				LineProfile(self,title,self.display[:,xloc],self.zunit,float(self.extents[1])/self.data.shape[0],self.UO.units[self.xyunit][1],xory='X')
			self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
		elif str(self.prof_box.GetStringSelection()) == 'Horizontal':
			
			#self.yline = self.im.axes.axhline(y=yloc,figure=self.figure)
			title = 'Horizontal Profile at y=%d'%yloc
			LineProfile(self,title,self.display[yloc,:],self.zunit,float(self.extents[0])/self.data.shape[1],self.UO.units[self.xyunit][1],xory='Y')
			self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
		elif str(self.prof_box.GetStringSelection()) == 'Arbitrary':
			self.lastx = xloc
			self.lasty = yloc
			self.canvas.Bind(wx.EVT_LEFT_DOWN, self.MakeArb)
		self.canvas.draw()
	
	def MakeArb(self, event):
		self.canvas.Bind(wx.EVT_LEFT_DOWN, None)
		self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
		xloc = int(round(self.frame.x))
		yloc = int(round(self.frame.y))
		nx = xloc-self.lastx
		ny = yloc-self.lasty
		if nx == 0:
			a = [self.lasty,yloc]
			a.sort()
			z = self.display[a[0]:a[1],xloc]
			if self.lasty > yloc: z = n.flipud(z)
		elif ny == 0:
			a = [self.lastx,xloc]
			a.sort()
			z = self.display[yloc,a[0]:a[1]]
			if self.lastx > xloc: z = n.flipud(z)
		else:
			m = ny/float(nx)
			b = self.lasty-m*self.lastx
			num = n.sqrt(n.square(nx)+n.square(ny))
			x = n.arange(self.lastx,int(round(self.frame.x)),nx/float(num))
			y = m*x+b
			z = []
			for i in range(len(x)): z.append(self.ZInterp(self.display,x[i],y[i]))
		title = 'Arbitrary Profile from (%d,%d) to (%d,%d)'%(self.lastx,self.lasty,xloc,yloc)
		if hasattr(self.subplot,'arrow'):
			#if hasattr(self,'proline'): self.proline.remove()
			self.proline = self.subplot.arrow(self.lastx,self.lasty,nx,ny,axes=self.subplot,ec='green', fc='green',lw=2,alpha=0.5,head_width=1,head_length=1)
			self.canvas.draw()
		LineProfile(self,title,n.array(z),self.zunit,n.sqrt(((float(self.extents[0])/self.data.shape[0])*nx)**2+((float(self.extents[0])/self.data.shape[0])*ny)**2)/len(z),self.UO.units[self.xyunit][1],xory='A')

	
	def ZInterp(self,data,x,y):
		x0 = int(n.floor(x))
		y0 = int(n.floor(y))
		x1 = int(n.ceil(x))
		y1 = int(n.ceil(y))
		z00 = data[y0,x0]
		z11 = data[y1,x1]
		z10 = data[y0,x1]
		z01 = data[y1,x0]
		if x-x0 == 0: t = 0
		elif x-x1 == 0: t=1
		else: t = (x-x0)/float(x1-x0)
		if y-y0 == 0: u = 0
		elif y-y1 == 0: u=1
		else: u = (y-y0)/float(y1-y0)
		z = (1-t)*(1-u)*z00 + t*(1-u)*z10 + t*u*z11 + (1-t)*u*z01
		return z
	
	def look3D(self, event):
		Plot3D(self, self.display)
	
	def AutoAdjust(self):
		zmax = n.mean(self.display)+2*n.std(self.display)
		zmin = n.mean(self.display)-2*n.std(self.display)
		if zmin < n.min(self.display): zmin = n.min(self.display)
		if zmax > n.max(self.display): zmax = n.max(self.display)
		self.SetLim(zmin=zmin,zmax=zmax)
		
	def add_line(self,data,lineN):
		self.lineN = lineN
		self.data[lineN,:] = data
		self.display[lineN,:] = self.displayConvert(data) 
		self.gauge.SetValue(lineN)
		if lineN == self.shape[0]-1: self.timer.Stop()
		elif not lineN ==self.shape[0]-1 and not self.timer.IsRunning(): self.timer.Start(1000)
		if lineN == 1 or not self.im:
			#self.subplot.hold(True)
			zmin = n.min(self.display)
			zmax = n.max(self.display)
			self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			interpolation=self.currinterp,vmin=zmin,vmax=zmax)
			self.colorbar.set_clim(vmin=zmin,vmax=zmax)
			self.colorbar.draw_all()
			#self.subplot.hold(True)
			self.canvas.draw()
		elif lineN%25==0:
			#zmin = n.min(self.data)
			#zmax = n.max(self.data)
			#self.colorbar.set_clim(vmin=zmin,vmax=zmax)
			#self.colorbar.draw_all()
			self.canvas.draw()
		else: self.im.set_data(self.display)
		#self.im.set_data(self.data)
	
	def ElapsedTime(self,event):
		#timeleft = ((time.time()-self.starttime)/lineN)*self.shape[0]
		if self.timer.IsRunning() and not len(self.frame.pages.keys()) == self.pagenum+1: self.timer.Stop()
		else:
			elapsed = time.time()-self.starttime
			minutes = str(int(elapsed)/60)
			seconds = str(int(elapsed)%60)
			if len(seconds)==1: seconds = '0'+seconds
			self.elapsedtime.SetLabel('Elapsed: %s min %s s'%(minutes,seconds))
	
	def Update(self,data,lineN,noline=False):
		if not noline: self.add_line(data,lineN) # Add the line to the data
	
		if hasattr(self, 'lastTime') and (1./(time.time()-self.lastTime)) < self.fps: #check if the max fps is being exceeded
			self.subplot.draw_artist(self.im)
			if self.bkim != None: self.bkim.figure.canvas.blit()
			if self.transspec != None:
				self.subplot.draw_artist(self.mask)
				self.mask.figure.canvas.blit()
			#if  'canvas' in dir(self.im.figure) and 'blit' in dir(self.im.figure.canvas):
			if  hasattr(self.im.figure,'canvas') and hasattr(self.im.figure.canvas,'blit'):
				self.im.figure.canvas.blit()
			else:
				self.canvas.draw()
			self.lastTime = time.time()
		elif not hasattr(self, 'lastTime'): self.lastTime = time.time()
		else: pass
		
	def ChangeCursor(self, event):
		self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
	
	def onselect(self,eclick,erelease):
		self.canvas.draw()
		x0,y0,x1,y1 = [eclick.xdata, eclick.ydata,erelease.xdata, erelease.ydata]
		if eclick.button == 1:
			self.writeRect(x0,y0,x1,y1)
		else:
			self.eraseRect(x0,y0,x1,y1)
		self.frame.specq.put(self.spec_mask)
		self.dispSpec(self.spec_mask,update=True)
	
	def sortCoord(self,x0,y0,x1,y1):
		list1 = [x0,x1]
		list2 = [y0,y1]
		list1.sort()
		list2.sort()
		return list1[0],list2[0],list1[1],list2[1]
	
	def writeRect(self,x0,y0,x1,y1):
		(xx,yx,xy,yy) = self.sortCoord(x0,y0,x1,y1)
		if yx <= self.lineN: yx = self.lineN
		else: pass
		gridx = self.GRIDX
		gridy = self.GRIDY
		if self.checker:
			self.spec_mask[yx:yy,xx:xy][::2*gridy,::gridx] = 1
			self.spec_mask[yx:yy,xx:xy][gridy::2*gridy,int(gridx/2.)::gridx] = 1
		else:
			self.spec_mask[yx:yy,xx:xy][::gridy,::gridx] = 1
		return self.spec_mask
	
	def eraseRect(self,x0,y0,x1,y1):
		(xx,yx,xy,yy) = self.sortCoord(x0,y0,x1,y1)
		if yx <= self.lineN: self.yx = self.lineN
		else: pass
		self.spec_mask[yx:yy,xx:xy] = 0
		return self.spec_mask
	
	def OnColor(self, event,color=None):
		if color == None: color = event.GetString()
		if color in self.cmap:
			if self.colinv.GetValue(): self.currcmap = self.cmap_r[color]
			else: self.currcmap = self.cmap[color]
			self.im.set_cmap(self.currcmap)
			self.colorbar.set_cmap(self.currcmap)
			self.colorbar.draw_all()
			self.canvas.draw()
		elif self.colors.GetSelection() == 0 and self.colinv.GetValue():
			self.currcmap = self.cmap_r[ws.DEFAULT_CMAP]
			self.im.set_cmap(self.currcmap)
			self.colorbar.set_cmap(self.currcmap)
			self.colorbar.draw_all()
			self.canvas.draw()
		else: pass
	
	def OnInterp(self, event):
		interp = event.GetString()
		if interp != self.interps[0]:
			self.currinterp = interp
			self.im.set_interpolation(interp)
			self.canvas.draw()
		else: pass
	
	def OnBackground(self, event):
		if event.GetString() == 'None': self.bkim = None
		else:
			self.bkim = self.subplot.imshow(copy(self.frame.pages[event.GetString()].display),origin='lower',\
				cmap=self.currcmap,interpolation=self.currinterp)
			self.bkim.figure.canvas.blit()
		self.im.figure.canvas.blit()
		self.canvas.draw()
	
	def OnHist(self, event):
		asdf = MakeHist(self,'Histogram '+self.SCAN,self.display)
	
	#def SetFrad(self, event):
		#frad = float(self.pix.GetLabel())
		#self.im.set_filterrad(frad)
		#self.currfrad = frad
		#self.canvas.draw()
	
	def OnFReset(self,event):
		self.display = deepcopy(self.data)
		self.im.set_data(self.display)
		self.canvas.draw()

	def OnFilter(self, event):
		frad = float(self.pix.GetLabel())
		filt = self.filters.GetStringSelection()
		if filt == 'Gaussian': self.display = gaussian_filter(self.display,frad)
		elif filt == 'Uniform': self.display = uniform_filter(self.display,frad)
		elif filt == 'Rank': self.display = rank_filter(self.display,-1,size=frad)
		elif filt == 'Maximum': self.display = maximum_filter(self.display,frad)
		elif filt == 'Median': self.display = median_filter(self.display,frad)
		elif filt == 'Minimum': self.display = minimum_filter(self.display,frad)
		elif filt == 'Laplace': self.display = laplace(self.display)
		elif filt == 'Sobel': self.display = sobel(self.display)
		elif filt == 'Gaussian Laplace': self.display = gaussian_laplace(self.display,frad)
		else: self.display = deepcopy(self.data)
		self.im.set_data(self.display)
		self.canvas.draw()

	def SetAlpha(self, event):
		alpha = int(self.alpha.GetValue())/10.
		self.im.set_alpha(alpha)
		self.canvas.draw()
		self.curralpha = alpha
	
	def OnFrad(self, event):
		frad = str(self.frad.GetValue())
		self.pix.SetLabel(str(int(frad)/10.))
	
	def OnNorm(self,event):
		norm = event.GetString()
		if norm =='yes':
			self.im.set_filternorm(1)
		elif norm =='no':
			self.im.set_filternorm(0)
		self.canvas.draw()
	
	def toggle_selector(self, event):
		pass
		#self.span.set_active(not self.span.get_active())
	
	def toggle_mask(self, event):
		self.subplot.clear()
		if self.mask == None:
			cmap=cm.spring
			cmap.set_bad((0,0,0),alpha=1)
			self.mask = self.subplot.pcolor(self.transspec,alpha=0.9,cmap=cmap,\
			vmin=0,vmax=1)
			self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			interpolation=self.currinterp)
			#self.im.figure.canvas.blit()
			#self.mask.figure.canvas.blit()
			self.canvas.draw()
		else:
			self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			interpolation=self.currinterp)
			self.mask = None
			self.canvas.draw()
	
	def toggle_spec(self, event):
		self.makeSpec()
	
	def dispSpec(self, data,update=False):
		if data.any():
			#self.ax = self.parent.canvas.figure.axes[0]
			#self.a = self.figure.add_subplot(111)
			self.spec_mask = data
			if self.transspec == None or update:
				mask = (~n.uint8(deepcopy(data)))-254
				self.transspec = nx.ma.masked_array(n.zeros(data.shape),mask=mask)
			else: pass
			if update:
				cmap = cm.spring
				cmap.set_bad((0,0,0),alpha=1)
				self.subplot.clear()
				self.mask = self.subplot.pcolor(self.transspec,alpha=0.7,cmap=cmap)
				self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
				interpolation=self.currinterp)
				#if 'canvas' in dir(self.im.figure) and 'blit' in dir(self.im.figure.canvas):
				if  hasattr(self.im.figure,'canvas') and hasattr(self.im.figure.canvas,'blit'):
					self.im.figure.canvas.blit()
					self.mask.figure.canvas.blit()
				else:
					self.canvas.draw()
			else:
				cmap=cm.spring
				cmap.set_bad((0,0,0),alpha=1)
				#self.subplot.hold(True)
				self.subplot.clear()
				self.mask = self.subplot.pcolor(self.transspec,alpha=0.7,cmap=cmap)
				self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
				interpolation=self.currinterp)
				zmin = n.min(self.data)
				zmax = n.max(self.data)
				self.colorbar.set_clim(vmin=zmin,vmax=zmax)
				self.colorbar.draw_all()
				self.canvas.draw()
	
	def SetLim(self,zmax=None,zmin=None):
		if zmax != None and zmin != None: pass
			#if not zmax > zmin: zmax = zmin + 0.01*abs(zmin)
		elif zmax == None: temp,zmax = self.im.get_clim()
		elif zmin == None: zmin,temp = self.im.get_clim()
		self.colorbar.set_clim(vmax=zmax,vmin=zmin)
		self.im.set_clim(vmax=zmax,vmin=zmin)
		#if zmax != None:
			#self.colorbar.set_clim(vmax=zmax)
			#self.im.set_clim(vmax=zmax)
		#if zmin != None:
			#self.colorbar.set_clim(vmin=zmin)
			#self.im.set_clim(vmin=zmin)
		self.subplot.draw_artist(self.im)
		self.colorbar.draw_all()
		self.canvas.draw()
	
	def SingleDisable(self):
		self.subtr.Disable()
		#self.frad.Disable()
		self.pix.Disable()
		self.colors.Disable()
		self.interp.Disable()
		self.showhist.Disable()
		#self.setrad.Disable()
	
	def CompEnable(self):
		self.showcont.Enable()
		self.disp_direc.Enable()
		self.show_scale.Enable()
		self.cspace.Enable()

	def _set_complete(self,fulldata):
		self.timer.Stop()
		self.package = fulldata
		self.displayprop.Enable()
		if hasattr(self.package,'IMAGEDATA'):
			#zout = self.package.GAIN_ZOUT[0]*10+1
			#self.ZSCALE = self.package.GAIN_ZHV[0]/zout
			self.data = self.package.IMAGEDATA[0][ws.DISPLAY_DIR]
			self.data_full = self.package.IMAGEDATA
			self.CompEnable()
			biases = []
			if hasattr(self.package,'N_BIAS_STEPS'):
				for i in range(self.package.N_BIAS_STEPS[0]+1):
					sampbias=str(self.package.SAMPLE_BIAS[0]+self.package.BIAS_STEPS[i][0]).split('.')
					sampbias = str(sampbias[0]+'.'+sampbias[1][0:2])
					biases.append(sampbias+' V')
			else:
				sampbias=str(self.package.SAMPLE_BIAS[0]).split('.')
				sampbias = str(sampbias[0]+'.'+sampbias[1][0:2])
				biases.append(sampbias+' V')
			layers = []
			for i in range(len(self.data_full)): layers.append('layer%d, %s'%(i,biases[i]))
			self.bias_layer.SetItems(layers)
			if len(layers) > 0: self.bias_layer.Enable()
			self.display = self.displayConvert(self.data,image=True)
			self.TYPE = self.package.TYPE
			self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			interpolation=self.currinterp)
			self.subtr.SetStringSelection('Line')
			self.OnSubtr(None)
			zmax = n.mean(self.display)+2*n.std(self.display)
			zmin = n.mean(self.display)-2*n.std(self.display)
			self.SetLim(zmax=zmax,zmin=zmin)
			if self.TYPE in self.frame.imagespec:
				self.toolbar._addSpecToggle()
				self.toolbar._addMaskToggle()
				self.dispSpec(self.package.SPEC_MASK)
				self.coords = str((0,0))
				self.spec_index = 1
				self.specsub = None
				self.pcolor_curr = None
				self.canvas.Bind(wx.EVT_KEY_DOWN, self.MoveSpec)
				self.getSpecPos()
			
			if hasattr(self.package,'iSPEC'):
				self.SPEC_DATA = self.package.iSPEC
			elif self.TYPE == 'imagewiv':
				self.SPEC_DATA = self.package.IV
			elif self.TYPE == 'imagewiz':
				self.SPEC_DATA = self.package.IZ
			elif self.TYPE == 'imagewzv':
				self.SPEC_DATA = self.package.ZV
		elif hasattr(self.package,'iSPEC'):
			self.subplot.clear()
			coords = str((0,0))
			asdf = SpecFigure(self,'name',external=[self,self.figure,self.canvas]\
			,spec_type = self.package.spec_type,toolbar=self.toolbar)
			asdf._drawOnChange(coords,self.package.iSPEC[self.package.iSPEC.keys()[0]])
			self.SingleDisable()
		
		
	#def refreshSpec(self,event):
		#self.setPlot(copy(self.data))
		#spec_mask = copy(self.dic['SPEC_MASK'])
		#mask = (~n.uint8(spec_mask))-254
		#self.spec_over = nx.ma.masked_array(n.zeros(spec_mask.shape),mask=mask)
		#cmap=cm.jet
		#cmap.set_bad((0,0,0),alpha=1)
		#self.subplot1.pcolor(self.spec_over,alpha=0.5,cmap=cmap)
		#self.canvas1.draw()
		#self.canvas1.SetFocus()
	
	def currentSpec(self,yloc,xloc):
		spec_mask = n.zeros(self.data.shape)
		spec_mask[yloc,xloc] = 1
		mask = (~n.uint8(spec_mask))-254
		self.spec_over = nx.ma.masked_array(n.zeros(spec_mask.shape),mask=mask)
		cmap=cm.gray_r
		cmap.set_bad((0,0,0),alpha=1)
		if not self.pcolor_curr:
			self.pcolor_curr = self.subplot.pcolor(self.spec_over,alpha=0.5,cmap=cmap)
		else:
			self.pcolor_curr = self.subplot.pcolor(self.spec_over,alpha=0.75,cmap=cmap)
		self.canvas.draw()
	
	def getSpecPos(self):
		self.locations = copy(n.uint8(self.package.SPEC_MASK)).nonzero()
		temp_mask = n.uint8(self.package.SPEC_MASK)
		lst = []
		for i in range(len(temp_mask)):
			lst.append(temp_mask[i].nonzero()[0])
		lst2 = []
		for i in range(len(lst)):
			lst2.append(len(lst[i]))
		self.udmove = lst2

	
	def MoveSpec(self, event):
		if self.TYPE in self.frame.imagespec and not self.specsub==None:
			KEY_PRESSED = event.GetKeyCode()
			sum = 0
			count = 0
			if KEY_PRESSED == wx.WXK_LEFT:
				self.spec_index -= 1
			elif KEY_PRESSED == wx.WXK_RIGHT:
				self.spec_index += 1
			elif KEY_PRESSED == wx.WXK_UP:
				while sum < self.spec_index:
					sum += self.udmove[count]
					count += 1
				self.spec_index += self.udmove[count-1]
			elif KEY_PRESSED == wx.WXK_DOWN:
				while sum < self.spec_index:
					sum += self.udmove[count]
					count += 1
				self.spec_index -= self.udmove[count-1]
			if self.spec_index < 0: self.spec_index = len(self.locations[0])-1
			elif self.spec_index > len(self.locations[0])-1: self.spec_index = 0
			xloc = int(self.locations[1][self.spec_index])
			yloc = int(self.locations[0][self.spec_index])
			self.currentSpec(yloc,xloc)
			self.x = str(xloc)
			self.y = str(yloc)
			self.coords = str((int(self.y),int(self.x)))
			if self.coords in self.SPEC_DATA.keys():
				self.specsub._drawOnChange(self.coords,self.SPEC_DATA[self.coords])
		elif self.TYPE in self.frame.imagespec and self.specsub == None: self.makeSpec()
	
	def makeSpec(self):
		if not self.specsub and self.TYPE == 'imagewiv':
			self.specsub = SpecFigure(self,self.package.NAME[0] + ' IV')
		elif not self.specsub and self.TYPE == 'imagewiz':
			self.specsub = SpecFigure(self,self.package.NAME[0] + ' IZ',spec_type='iz')
		elif not self.specsub and self.TYPE == 'imagewvz':
			self.specsub = SpecFigure(self,self.package.NAME[0] + ' VZ',spec_type='vz')
		else: pass



class Scanning2(object):
	'''
	This class coordinates the notebook panels for the image viewing and analysis. It starts by opening 2
	sample panels which show off to allow the user to mess around with the data analysis features of the
	program.
	'''
	cax = None
	imagespec = ['imagewiv','imagewzv','imagewiz']
	N_ALLOWED_TABS = ws.N_ALLOWED_TABS
	IM_ASPECT_W = ws.IM_ASPECT_W
	IM_ASPECT_H = ws.IM_ASPECT_H
	IM_ASPECT_SIZE = ws.IM_ASPECT_SIZE
	def __init__(self,nb,dataq=None,specq=None,homefrm=None,offset=(None,None)):
		self.fig = Figure((7,6), 100)
		self.nb = nb
		self.offsetfig,self.offsetcanvas = offset
		if homefrm==None: editor=self.editor
		else: editor=homefrm.editor
		self.pages = {}
		self.x = None
		self.y = None
		self.ivsub = None
		self.coords = None
		self.package = None
		self.timelast = 0
		self.update = 0
		self.dataq = dataq
		self.specq = specq
		self.count = 0

		# Initialise the timer - wxPython requires this to be connected to
		# the receiving event handler
		self.t = wx.Timer(self, TIMER_ID)
		self.t.Start(100)

		# Open the sample panels
		number = 0
		fig = Figure((ws.IM_ASPECT_W,ws.IM_ASPECT_H), ws.IM_ASPECT_SIZE)
		asdf = FakePkg()
		self.pages['00000'] = NotebookPage(self,self.nb,number,editor=editor) # an image page
		self.pages['00000'].addToNotebook('00000') # append the page to the notebook
		self.pages['00000'].addPlot(fig,asdf,fake=True) # plot the data
		self.pages['00000'].lineN = 100
		
		fig = Figure((ws.IM_ASPECT_W,ws.IM_ASPECT_H), ws.IM_ASPECT_SIZE)
		asdf = FakePkg()
		self.pages['00001'] = NotebookSpec(self,self.nb,number) # a spectroscopy page
		self.pages['00001'].addToNotebook('00001') # append the page to the notebook
		self.pages['00001'].addPlot(fig,asdf,None) # plot the data
		
		sizer2 = wx.BoxSizer()
		sizer2.Add(self.nb, 1, wx.GROW, 0)
		self.SetSizer(sizer2)
		self.Bind(wx.EVT_TIMER, self.onTimer, id=TIMER_ID)
		self.Bind(wx.EVT_CLOSE, self.onClose)
		
		# Note that event is a MplEvent
		self.statusBar = wx.StatusBar(self, -1)
		self.statusBar.SetFieldsCount(1)
		self.SetStatusBar(self.statusBar)
		#self.Show()

	
	def getData(self,editor=None,datapkg=None):
		'''
		Monitors the queue for any incoming data. If data is present,
		this function moves the data onto the notebook page. If the data comes
		from a new scan, a new page is added to the notebook.

		Keyword Arguments --
		editor - allows the editor object to be passed to the page if not
		already defined as an attribute of the class
		datapkg - used if data is already present, but other 
		'''
		if datapkg: pass
		else:
			try:
				datapkg = self.dataq.get(block=False)
				data = datapkg.data
				lineN = datapkg.LINE
				close = datapkg.close
				extent = datapkg.EXTENT
				datapkg.SCAN = str(datapkg.SCAN)
			except:
				datapkg = FakePkg()
				line = None
				close = False
		
		if datapkg.DATATYPE == 'line' or datapkg.DATATYPE == 'spec':
			if str(datapkg.SCANSTAMP) in self.pages.keys():
				self.pages[str(datapkg.SCANSTAMP)].Update(data,lineN)
			else:
				number = len(self.pages.keys())+2 #add 2 because of the stm and editor tabs
				fig = Figure((self.IM_ASPECT_W,self.IM_ASPECT_H), self.IM_ASPECT_SIZE)
				for key in self.pages.keys():
					if datapkg.SCAN in self.pages[key].SCAN:
						xs = 'XXXX'
						while xs in self.pages.keys():
							xs = xs+'X'
						self.nb.SetPageText(self.pages[key].pagenum,xs)
						self.pages[xs] = self.pages[key] # self.pages keeps track of the notebook tabs
						self.pages[xs].SCAN = xs
						self.pages.__delitem__(key)
				self.pages[str(datapkg.SCANSTAMP)] = NotebookPage(self,self.nb,number,editor=editor)
				self.pages[str(datapkg.SCANSTAMP)].addToNotebook(str(datapkg.SCAN))
				if datapkg.TYPE in self.imagespec:
					self.pages[str(datapkg.SCANSTAMP)].addPlot(fig,datapkg)
				else:
					self.pages[str(datapkg.SCANSTAMP)].addPlot(fig,datapkg)
				#self.restrictNPages()
				if datapkg.DATATYPE == 'line': self.pages[str(datapkg.SCANSTAMP)].Update(data,lineN)
				elif datapkg.DATATYPE == 'spec': self.pages[str(datapkg.SCANSTAMP)].dispSpec(data)
		else: pass
	
	def SpecPage(self,datapkg):
		'''
		Adds a spectroscopy page to the notebook. Similar to getData().
		'''
		number = len(self.pages.keys())+2
		fig = Figure((self.IM_ASPECT_W,self.IM_ASPECT_H), self.IM_ASPECT_SIZE)
		for key in self.pages.keys():
			if datapkg.SCAN_NUMBER in self.pages[key].SCAN:
				xs = 'XXXX'
				while xs in self.pages.keys():
					xs = xs+'X'
				self.nb.SetPageText(self.pages[key].pagenum,xs)
				self.pages[xs] = self.pages[key]
				self.pages[xs].SCAN = xs
				self.pages.__delitem__(key)
		self.pages[str(datapkg.SCANSTAMP)] = NotebookSpec(self,self.nb,number)
		self.pages[str(datapkg.SCANSTAMP)].addToNotebook(str(datapkg.SCAN_NUMBER))
		self.pages[str(datapkg.SCANSTAMP)].addPlot(fig,datapkg,datapkg.TYPE[-2:])
		#self.restrictNPages()
	
	#def restrictNPages(self):
		#'''
		#Restricts the number of pages allowed in the notebook. First check if
		#tabs have exceeded the allowed number and if it has, proceeds to delete the
		#first available tab in the notebook.
		#'''
		#if len(self.pages.keys()) > self.N_ALLOWED_TABS:
			#delpg = None
			#for page in self.pages:
				#if self.pages[page].pagenum == 2:
					#delpg = page
				#else: self.pages[page].pagenum -= 2
			#if delpg:
				#self.pages[delpg].delFromNotebook(None)
				#self.pages.__delitem__(delpg)
		#else: pass
	
	def _completed(self,fulldata):
		'''
		Once the full data package comes through the data collectors, all of
		the attributes of the scan are set.
		'''
		self.pages[str(fulldata.SCANSTAMP)]._set_complete(fulldata)

	def UpdateStatusBar(self, event):
		'''
		This function displays the xy coordinates in the statusbar. Needs to be outside the
		tab-level class because status bars are not unique to individual tabs.
		'''
		if event.inaxes:
			self.x, self.y = event.xdata, event.ydata
			self.x = int(round(self.x))
			self.y = int(round(self.y))
			try:
				if self.nb.GetCurrentPage().NB_TYPE == 'image':
					datapt = self.nb.GetCurrentPage().display[self.y][self.x]
				else: datapt = ''
			except: datapt = ''
			if datapt < 0: datapt = str(datapt)[0:6]
			else: datapt = str(datapt)[0:5]
			infostr = "x= "+str(self.x)[:5]+"  y="+str(self.y)[:5]+"  z="+datapt
			self.statusBar.SetStatusText((infostr),0)
	
	def finalData(self):
		'''
		Figures out what to do with the data received from
		the scan.
		
		'''
		data = self.panel.saveq.get()
		key = data.TYPE
		images = ['image','imagewiv','imagewiz','imagewzv','multibias','continuous']
		single_spec = ['singleiv','singleiz','singlezv']
		if key in images:
			self._completed(data)
		elif key in single_spec:
			self.SpecPage(data)
			self._completed(data)
			#iv_fig = SpecFigure(self,'IV Scan')
			#coords = str((0,0))
			#iv_fig._drawOnChange(coords,data.IV[coords])
		#elif key == 'singleiz':
			#iz_fig = SpecFigure(self,'IZ Scan',spec_type='iz')
			#coords = str((0,0))
			#iz_fig._drawOnChange(coords,data.IZ[coords])
		#elif key == 'singlezv':
			#zv_fig = SpecFigure(self,'ZV Scan',spec_type='zv')
			#coords = str((0,0))
			#zv_fig._drawOnChange(coords,data.ZV[coords])
		elif key == 'recovery':
			self.panel.newtree.treebytreename['image'].data['Offsets'][sv.XOFF[2]][0] = data.XOFF[0]
			self.panel.newtree.treebytreename['image'].data['Offsets'][sv.YOFF[2]][0] = data.YOFF[0]
			self.panel.newtree.treebytreename['image'].data['Image Parameters'][sv.SAMPLE_BIAS[2]][0] = data.SAMPLE_BIAS[0]
	
	def onTimer(self, evt):
		self.getData(editor=self.editor)
		if not self.panel.saveq.empty():
			self.finalData()

	def onClose(self, evt):
		self.t.Stop()
		evt.Skip()



class SpNavigationToolbar(NavigationToolbar2WxAgg):
	"""
	Extend the default wx toolbar with your own event handlers
	"""
	ON_UP = wx.NewId()
	ON_DOWN = wx.NewId()
	ON_ALL = wx.NewId()
	def __init__(self, parent, canvas, cankill):
		NavigationToolbar2WxAgg.__init__(self, canvas)
		self.parent = parent
		if self.parent.spec_type == 'iv':
			self.AddSimpleTool(self.ON_DOWN, _load_bitmap('stock_down.xpm'),
						'Move down a z-layer', 'Move down a z-layer')
			wx.EVT_TOOL(self, self.ON_DOWN, self._on_down)
			self.AddSimpleTool(self.ON_UP, _load_bitmap('stock_up.xpm'),
						'Move up a z-layer', 'Move up a z-layer')
			wx.EVT_TOOL(self, self.ON_UP, self._on_up)
			self.AddSimpleTool(self.ON_ALL, _load_bitmap('stock_refresh.xpm'),'Display All', 'Display All')
			wx.EVT_TOOL(self, self.ON_ALL, self._on_all)
		else: pass

	def _on_up(self, evt):
		self.parent.index += 1
		if self.parent.index > self.parent.max_index:
			self.parent.index = self.parent.max_index
		self.parent.plotSelection(self.parent.index,self.parent.display,self.parent.subplot2,labels=False)
		self.parent.plotSelection(self.parent.index,self.parent.data,self.parent.subplot,labels=False)
		self.parent.mode=0
		evt.Skip()
	
	def _on_down(self, evt):
		self.parent.index -= 1
		if self.parent.index < 0:
			self.parent.index = 0
		self.parent.plotSelection(self.parent.index,self.parent.display,self.parent.subplot2,labels=False)
		self.parent.plotSelection(self.parent.index,self.parent.data,self.parent.subplot,labels=False)
		self.parent.mode=1
		evt.Skip()
		
	def _on_all(self, evt):
		if self.parent.pdir == 0: self.parent.pdir = 1
		else: self.parent.pdir = 0
		self.parent.plotAll(self.parent.pdir,self.parent.display,self.parent.subplot2,labels=False)
		self.parent.plotAll(self.parent.pdir,self.parent.data,self.parent.subplot,labels=False)
		self.parent.mode=2
		evt.Skip()



class NotebookSpec(wx.Panel):
	'''
	A complementary class to NotebookPage. This handles the data/data analysis techniques for spectroscopy
	style data.
	'''
	NB_TYPE = 'spec'
	ASPECT_W = ws.ASPECT_W
	ASPECT_H = ws.ASPECT_H
	ASPECT_SIZE = ws.ASPECT_SIZE
	TITLE_SIZE = ws.TITLE_SIZE
	AXES_SIZE = ws.AXES_SIZE
	DEFAULT_COLOR = ws.DEFAULT_COLOR
	POINT_TYPE = ws.POINT_TYPE
	LINE_WEIGHT = ws.LINE_WEIGHT
	labels = {'i':ws.CURRENT_LABEL,'v':ws.BIAS_LABEL,'z':ws.HEIGHT_LABEL,\
	  'I':ws.CURRENT_LABEL,'V':ws.BIAS_LABEL,'Z':ws.HEIGHT_LABEL}
	unit_types = {}
	unit_types['I']=['Picoamps','Nanoamps','Microamps']
	unit_types['V']=['Millivolts','Volts']
	unit_types['Z']=['Volts','Angstroms','Nanometers','Microns']
	subplots = {'plot0':None,'plot1':None}
	pdir = 0
	max_index = 0
	gradpts = 3
	polyorder = 1
	sgderiv = 1
	def __init__(self,frame,parent,pagenum):
		wx.Panel.__init__(self,parent)
		self.parent = parent
		self.frame = frame
		self.pagenum = pagenum
	
	def addPlot(self,figure,datapkg,spec_type,addlabels=None):
		self.figure = figure
		self.spec_type = spec_type
		if hasattr(datapkg,'ZSCALE'): self.ZSCALE = datapkg.ZSCALE
		else: self.ZSCALE = 1
		if hasattr(datapkg, 'ZOUT'): self.ZOUT = datapkg.ZOUT
		else: self.ZOUT = 1.0
		if hasattr(datapkg, 'ZHV'): self.ZHV = datapkg.ZHV
		else: self.ZHV = 10.0
		self.UO = datapkg.UO
		self.canvas = FigureCanvasWxAgg(self, -1, figure)
		self.toolbar = SpNavigationToolbar(self,self.canvas, True)
		self.toolbar.Realize()
		self._set_layout(addlabels=addlabels)
		self.subplot = figure.add_subplot(211)
		self.subplot2 = figure.add_subplot(212)
		self.subplots = {'plot0':self.subplot,'plot1':self.subplot2}
		### Settings from old spec viewer ###
		self._resizeflag = True
		self.x = None
		self.y = None
		self.active = True
		self.index = 0
		self.max_index = 0
		#self.init_plot_data()
		xloc,yloc=0,0
		if spec_type != None:
			com='self.data=datapkg.'+string.upper(spec_type)+'[str((int(yloc),int(xloc)))]'
			exec com
			self.max_index = len(self.data)-1
		else:
			data = n.arange(1000)*0.01
			self.data = [[[data,(-n.sin(data*8.)-0.5*n.sin(data*2.)+n.random.random(1000))*15],[data,(n.sin(data*8.)+0.5*n.sin(data*2.)+n.random.random(1000))*15]]]
		self.display = deepcopy(self.data)
		self.plotSelection(0,self.data,self.subplot)
		####################################
		self.canvas.draw()
	
	def _set_layout(self,addlabels=None):
		panel_b = wx.Panel(self, -1)
		panel_c = wx.Panel(self, -1)
		panel_c.SetMinSize((127, 27))
		sizer = wx.FlexGridSizer(3, 1, 0, 0)
		sizer.AddGrowableRow(0,1)
		sizer.AddGrowableCol(0,1)
		sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW, 0)
		sizer.Add(self.toolbar, 1, wx.GROW, 0)
		sizer.Add(panel_c, 0, wx.GROW, 0)
		sizer2 = wx.BoxSizer(wx.VERTICAL)
		
		unitbox = wx.StaticBox(self, -1, 'Units')
		self.unit_type = wx.Choice(self, -1, choices=[])
		self.use_unit = wx.Choice(self, -1, choices=[])
		unitsizer1 = wx.BoxSizer(wx.HORIZONTAL)
		unitsizer2 = wx.BoxSizer(wx.HORIZONTAL)
		self.unit_type.SetMinSize((127,27))
		self.unit_type.Disable()
		self.use_unit.SetMinSize((127,27))
		self.use_unit.Disable()
		sizer2i = wx.StaticBoxSizer(unitbox,wx.VERTICAL)
		sizer2i.Add(self.unit_type, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2i.Add(self.use_unit, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2i.Add(unitsizer1, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2i.Add(unitsizer2, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)

		savgol = wx.StaticBox(self, -1, 'Savitzky-Golay')
		savsizer = wx.BoxSizer(wx.HORIZONTAL)
		sgptssizer = wx.BoxSizer(wx.HORIZONTAL)
		sgpts_label = wx.StaticText(self,-1,'# Points:')
		self.sgpts = wx.SpinCtrl(self, -1, str(5), min=1, max=30)
		sgpts_label.SetMinSize((63,27))
		self.sgpts.SetMinSize((63,27))
		sgptssizer.Add(sgpts_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		sgptssizer.Add(self.sgpts, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		pordersizer = wx.BoxSizer(wx.HORIZONTAL)
		porder_label = wx.StaticText(self,-1,'PolyOrder:')
		self.porder = wx.SpinCtrl(self, -1, str(1), min=1, max=5)
		porder_label.SetMinSize((63,27))
		self.porder.SetMinSize((63,27))
		pordersizer.Add(porder_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		pordersizer.Add(self.porder, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		dordersizer = wx.BoxSizer(wx.HORIZONTAL)
		dorder_label = wx.StaticText(self,-1,'DerivOrder:')
		self.dorder = wx.SpinCtrl(self, -1, str(1), min=0, max=5)
		dorder_label.SetMinSize((63,27))
		self.dorder.SetMinSize((63,27))
		dordersizer.Add(dorder_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		dordersizer.Add(self.dorder, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		self.sgupdate = wx.Button(self, -1, 'Apply')
		self.sgupdate.SetMinSize((127,27))
		sizer2f = wx.StaticBoxSizer(savgol,wx.VERTICAL)
		sizer2f.Add(sgptssizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(pordersizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(dordersizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(self.sgupdate, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		
		fftbox = wx.StaticBox(self, -1, 'Fourier Transform')
		self.fftlog = wx.CheckBox(self, -1, label='Log Display')
		self.showfft = wx.Button(self, -1, 'Apply FFT')
		fftsizer = wx.BoxSizer(wx.HORIZONTAL)
		self.fftlog.SetMinSize((127,27))
		self.showfft.SetMinSize((127,27))
		sizer2g = wx.StaticBoxSizer(fftbox,wx.VERTICAL)
		sizer2g.Add(self.fftlog, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(self.showfft, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		limbox = wx.StaticBox(self, -1, 'Limits')
		self.plotnumber = wx.Choice(self,-1,choices=self.subplots.keys())
		self.plotnumber.SetMinSize((127,27))
		lims0=wx.BoxSizer(wx.HORIZONTAL)
		lims1=wx.BoxSizer(wx.HORIZONTAL)
		lims2=wx.BoxSizer(wx.HORIZONTAL)
		lims3=wx.BoxSizer(wx.HORIZONTAL)
		lims4=wx.BoxSizer(wx.HORIZONTAL)
		xtxt = wx.StaticText(self,-1,'Xlims  ')
		xmi = wx.StaticText(self,-1,'min')
		xmi.SetMinSize((27,27))
		xma = wx.StaticText(self,-1,'max')
		xma.SetMinSize((28,27))
		ytxt = wx.StaticText(self,-1,'  Ylims')
		ymi = wx.StaticText(self,-1,'min')
		ymi.SetMinSize((27,27))
		yma = wx.StaticText(self,-1,'max')
		yma.SetMinSize((28,27))
		self.xminl = wx.Slider(self, -1, 0, -10, 10, (-1, -1), (250, -1), 
		wx.SL_AUTOTICKS | wx.SL_VERTICAL | wx.SL_LABELS)
		self.xminl.SetMinSize((22,127))
		self.xmin = None
		self.xmaxl = wx.Slider(self, -1, 0, -10, 10, (-1, -1), (250, -1), 
		wx.SL_AUTOTICKS | wx.SL_VERTICAL | wx.SL_LABELS)
		self.xmaxl.SetMinSize((22,127))
		self.xmax = None
		#ylims=wx.BoxSizer(wx.HORIZONTAL)
		self.yminl = wx.Slider(self, -1, 0, -10, 10, (-1, -1), (250, -1), 
		wx.SL_AUTOTICKS | wx.SL_VERTICAL | wx.SL_LABELS)
		self.yminl.SetMinSize((22,127))
		self.ymin = None
		self.ymaxl = wx.Slider(self, -1, 0, -10, 10, (-1, -1), (250, -1), 
		wx.SL_AUTOTICKS | wx.SL_VERTICAL | wx.SL_LABELS)
		self.ymaxl.SetMinSize((22,127))
		self.ymax = None
		self.xmult_label = wx.StaticText(self,-1,'XMult/10')
		self.xmult_label.SetMinSize((62,27))
		self.xmult = wx.SpinCtrl(self,-1,'10',name='XMultiplier',min=1,max=99)
		self.xmult.SetMinSize((42,27))
		self.xmult_val = wx.StaticText(self,-1,'1.0')
		self.xmult_val.SetMinSize((22,27))
		self.ymult_label = wx.StaticText(self,-1,'YMult/10')
		self.ymult_label.SetMinSize((62,27))
		self.ymult = wx.SpinCtrl(self,-1,'10',name='YMultiplier',min=1,max=99)
		self.ymult.SetMinSize((42,27))
		self.ymult_val = wx.StaticText(self,-1,'1.0')
		self.ymult_val.SetMinSize((22,27))
		self.limapply = wx.Button(self, -1, 'Apply')
		self.limapply.SetMinSize((127,27))
		sizer2h = wx.StaticBoxSizer(limbox,wx.VERTICAL)
		lims0.Add(xtxt, 0, wx.ADJUST_MINSIZE|wx.RIGHT, 10)
		lims0.Add(ytxt, 0, wx.ADJUST_MINSIZE|wx.LEFT, 10)
		lims1.Add(xmi, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 2)
		lims1.Add(xma, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 2)
		lims1.Add(ymi, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 2)
		lims1.Add(yma, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 2)
		lims2.Add(self.xminl, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		lims2.Add(self.xmaxl, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		lims2.Add(self.yminl, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		lims2.Add(self.ymaxl, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		lims3.Add(self.xmult_label, 0, wx.ADJUST_MINSIZE|wx.TOP, 10)
		lims3.Add(self.xmult, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		lims3.Add(self.xmult_val, 0, wx.ADJUST_MINSIZE|wx.TOP, 10)
		lims4.Add(self.ymult_label, 0, wx.ADJUST_MINSIZE|wx.TOP, 10)
		lims4.Add(self.ymult, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		lims4.Add(self.ymult_val, 0, wx.ADJUST_MINSIZE|wx.TOP, 10)
		sizer2h.Add(self.plotnumber, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2h.Add(lims0, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTRE|wx.ALL, 5)
		sizer2h.Add(lims1, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2h.Add(lims2, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2h.Add(lims3, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2h.Add(lims4, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2h.Add(self.limapply, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)

		closebox = wx.StaticBox(self, -1, 'Close Page')
		self.close_this = wx.Button(self, -1, 'Close')
		#closesizer = wx.BoxSizer(wx.HORIZONTAL)
		self.close_this.SetMinSize((127,27))
		sizer2i = wx.StaticBoxSizer(closebox,wx.VERTICAL)
		sizer2i.Add(self.close_this, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		self.close_this.Bind(wx.EVT_BUTTON, self.delFromNotebook)

		sizer2.Add(sizer2i, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2f, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2g, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2h, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2i, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(panel_b, 1, wx.EXPAND, 0)
		if addlabels != None:
			grid_sizer_1 = wx.FlexGridSizer(1, 3, 0, 0)
			grid_sizer_1.AddGrowableRow(0,1)
			grid_sizer_1.AddGrowableCol(0,1)
			grid_sizer_1.Add(sizer, 1, wx.GROW, 0)
			grid_sizer_1.Add(sizer2, 1, wx.GROW, 0)
			grid_sizer_1.Add(addlabels, 1, wx.GROW, 0)
		else:
			grid_sizer_1 = wx.FlexGridSizer(1, 2, 0, 0)
			grid_sizer_1.AddGrowableRow(0,1)
			grid_sizer_1.AddGrowableCol(0,1)
			grid_sizer_1.Add(sizer, 1, wx.GROW, 0)
			grid_sizer_1.Add(sizer2, 1, wx.GROW, 0)
		self.SetSizer(grid_sizer_1)
		self.canvas.mpl_connect('motion_notify_event', self.frame.UpdateStatusBar)
		self.sgupdate.Bind(wx.EVT_BUTTON, self.OnSG)
		self.showfft.Bind(wx.EVT_BUTTON, self.OnFFT)
		self.limapply.Bind(wx.EVT_BUTTON, self.OnLimits)
		self.xmult.Bind(wx.EVT_SPINCTRL, self.OnXSpin)
		self.ymult.Bind(wx.EVT_SPINCTRL, self.OnYSpin)
		self.unit_type.Bind(wx.EVT_CHOICE, self.OnUnitSelect)
		self.use_unit.Bind(wx.EVT_CHOICE, self.OnUseUnit)

	def OnXSpin(self,event): self.xmult_val.SetLabel(str(int(self.xmult.GetValue())/10.))
	def OnYSpin(self,event): self.ymult_val.SetLabel(str(int(self.ymult.GetValue())/10.))

	def OnUnitSelect(self,event):
		unit=self.unit_type.GetStringSelection()
		if unit in self.unit_types.keys():
			self.use_unit.SetItems(self.unit_types[unit])
	
	def OnUseUnit(self,event):
		unit_type=self.use_unit.GetStringSelection()
		if hasattr(self,'package'):
			if unit_type == 'Z':
				self.display=self.UO._ConvertZScale(self.data,self.UO.ZVOLTS,self.UO.units[self.zunit][0],self.package.GAIN_ZHV[0],self.package.GAIN_ZOUT[0])
			elif unit_type == 'V':
				self.display=self.UO._Convert(self.data,self.UO.BIAS,self.UO.units[unit_type][0])
			elif unit_type == 'I':
				self.display=self.UO._Convert(self.data,self.UO.AMPS,self.UO.units[unit_type][0])

	def OnSG(self,event):
		gradpts = int(self.sgpts.GetValue())
		polyorder = int(self.porder.GetValue())
		sgderiv = int(self.dorder.GetValue())
		if sgderiv > polyorder:
			self.porder.SetValue(int(sgderiv))
			polyorder = sgderiv
		self.display = deepcopy(self.data)
		coeff = sg.calc_coeff(gradpts, polyorder, sgderiv)
		dx = float(self.display[0][0][0][-1:][0]-self.display[0][0][0][0])/len(self.display[0][0][0])
		corr = (1./dx)**sgderiv
		#if sgderiv != 0: corr *= -1
		#else: corr *= 1
		for i in range(len(self.display)):
			for j in range(2):
				#self.display[i][j][1] = self.display[i][j][1]-n.mean(self.display[i][j][1])
				self.display[i][j][1] = corr*sg.savitzky_golay(self.display[i][j][1],kernel=2*gradpts+1
				  ,order=polyorder,deriv=sgderiv)
				#self.display[i][j][1] = corr*sg.smooth(self.display[i][j][1],coeff)
		self.plotSelection(self.index,self.display,self.subplot2,labels=False)
	
	def OnFFT(self,event):
		for i in range(len(self.display)):
			for j in range(2):
				#self.display[i][j][1] = self.display[i][j][1]-n.mean(self.display[i][j][1])
				fft_data = n.fft.fft(self.display[i][j][1])
				self.display[i][j][1] = n.sqrt(n.real(fft_data)**2+n.imag(fft_data)**2)
		self.plotSelection(self.index,self.display,self.subplot2,labels=False)
	
	def plotSelection(self,index,data,subplot,labels=True):
		colors = ['g','r','b','c','y','m']
		xmax,xmin,ymax,ymin = (-10.1,10.1,-10.1,10.1)
		for j in range(2):
			if xmax < n.array(data[index][j][0]).max(): xmax = n.array(data[index][j][0]).max()
			if xmin > n.array(data[index][j][0]).min(): xmin = n.array(data[index][j][0]).min()
			if ymax < n.array(data[index][j][1]).max(): ymax = n.array(data[index][j][1]).max()
			if ymin > n.array(data[index][j][1]).min(): ymin = n.array(data[index][j][1]).min()
		if abs(ymax - ymin)<0.1:
			ymax += 0.01
			ymin -= 0.01
		subplot.clear()
		znf = subplot.plot(data[index][0][0],data[index][0][1],
		 self.POINT_TYPE,color=self.DEFAULT_COLOR[0],lw=self.LINE_WEIGHT)
		znr = subplot.plot(data[index][1][0],data[index][1][1],
		 self.POINT_TYPE,color=self.DEFAULT_COLOR[1],lw=self.LINE_WEIGHT)
		self.figure.subplots_adjust(left=0.15, bottom=0.05,top=0.9,right=0.85)
		axcolor = 'w'
		#Set some plot attributes
		if labels == True:
			subplot.set_title('Scan No. '+self.SCAN)
			subplot.set_ylabel("y Data (V)", fontsize = self.AXES_SIZE)
			subplot.set_xlabel("x Data (V)", fontsize = self.AXES_SIZE)
		#subplot.set_xlabel("Tip Bias (V)", fontsize = 16)
		#subplot.set_ylabel("Tunneling Current (mA)", fontsize = 16)
		subplot.set_xlim([xmin, xmax])
		subplot.set_ylim([ymin, ymax])
		subplot.legend([znf,znr],['z'+str(index)+'f', 'z'+str(index)+'r'], shadow=True)
		self.canvas.draw()
	
	def plotAll(self,direction,data,subplot,labels=True):
		layers = len(data)
		colors = ['g','r','b','c','y','m']
		xmax,xmin,ymax,ymin = (-10,10,-10,10)
		for i in range(layers):
			if xmax < n.array(data[i][direction][0]).max(): xmax = n.array(data[i][direction][0]).max()
			if xmin > n.array(data[i][direction][0]).min(): xmin = n.array(data[i][direction][0]).min()
			if ymax < n.array(data[i][direction][1]).max(): ymax = n.array(data[i][direction][1]).max()
			if ymin > n.array(data[i][direction][1]).min(): ymin = n.array(data[i][direction][1]).min()
		if abs(ymax - ymin)<0.1:
			ymax += 0.01
			ymin -= 0.01	
		subplot.clear()
		count = 0
		zn = []
		zind = []
		for i in range(layers):
			if direction == 0: direc = 'f'
			else: direc = 'r'
			zind.append('z'+str(i)+direc)
			zn.append(subplot.plot(data[i][direction][0],data[i][direction][1],\
			self.POINT_TYPE,color=self.DEFAULT_COLOR[count],lw=self.LINE_WEIGHT))
			count += 1
		self.figure.subplots_adjust(left=0.1, bottom=0.1,top=0.85,right=0.9)
		axcolor = 'w'
		#Set some plot attributes
		if labels==True and hasattr(self,package):
			subplot.set_title('Scan No. '+self.SCAN)
			subplot.set_xlabel(self.xlabel, fontsize = self.AXES_SIZE)
			subplot.set_ylabel(self.ylabel, fontsize = self.AXES_SIZE)
		subplot.set_xlim([xmin, xmax])
		subplot.set_ylim([ymin, ymax])
		subplot.legend(zn,zind, shadow=True)
		self.canvas.draw()
	
	def addToNotebook(self,title):
		self.parent.AddPage(self,title)
		self.SCAN = title
		self.parent.SetSelection(self.pagenum)
	
	def delFromNotebook(self,event): self.parent.RemovePage(self.parent.GetSelection())
	
	def OnLimits(self,event):
		plt=self.subplots[self.plotnumber.GetStringSelection()]
		try:
			self.xmin = float(self.xminl.GetValue())*float(self.xmult.GetValue())/10
			self.xmax = float(self.xmaxl.GetValue())*float(self.xmult.GetValue())/10
			if self.xmax < self.xmin: self.xmax = self.xmin+1
			xlims = (self.xmin,self.xmax)
		except: xlims = (-1,1)
		try:
			self.ymin = float(self.yminl.GetValue())*float(self.ymult.GetValue())/10
			self.ymax = float(self.ymaxl.GetValue())*float(self.ymult.GetValue())/10
			if self.ymax < self.ymin: self.ymax = self.ymin+1
			ylims = (self.ymin,self.ymax)
		except: ylims = (-1,1)
		self.setLim(plt,xlims,ylims)

	def setLim(self,subplot,xlims,ylims):
		subplot.set_xlim([xlims[0], xlims[1]])
		subplot.set_ylim([ylims[0], ylims[1]])
		self.canvas.draw()

	def _set_complete(self,fulldata):
		self.package = fulldata
		self.UO = fulldata.UO
		self.singletype = self.package.TYPE[-2:]
		typ0 = self.singletype[0]
		typ1 = self.singletype[1]
		self.ylabel = self.labels[typ0]
		self.xlabel = self.labels[typ1]
		self.unit_type.SetItems([string.upper(typ0),string.upper(typ1)])
		self.unit_type.Enable()
		self.use_unit.Enable()
